From dd64a2deed069c49760268cafb9150cac8bb00a1 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 27 Aug 2024 11:28:10 +0200
Subject: [PATCH 01/56] Start webhook implementation

---
 Model/Carrier/UData.php         |  11 ++-
 Observer/OrderCreateWebhook.php | 119 ++++++++++++++++++++++++++++++++
 Observer/OrderUpdateWebhook.php |  76 ++++++++++++++++++++
 etc/events.xml                  |   6 ++
 etc/frontend/di.xml             |   8 +++
 5 files changed, 218 insertions(+), 2 deletions(-)
 create mode 100644 Observer/OrderCreateWebhook.php
 create mode 100644 Observer/OrderUpdateWebhook.php

diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index 47b5d8b..a7e5d2e 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -12,12 +12,19 @@ class UData
      *
      * @var string
      */
-    public const TRACKING = 'https://api.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
+    public const TRACKING = 'https://api.dev.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
 
     /**
      * Rates API Endpoint
      *
      * @var string
      */
-    public const RATES_ENDPOINT = 'https://api.bobgo.co.za/rates-at-checkout/magento';
+    public const RATES_ENDPOINT = 'https://api.dev.bobgo.co.za/rates-at-checkout/magento';
+
+    /**
+     * Order create/update webhook URL
+     *
+     * @var string
+     */
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
new file mode 100644
index 0000000..f301cc8
--- /dev/null
+++ b/Observer/OrderCreateWebhook.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use Magento\Framework\Event\Observer;
+use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use BobGroup\BobGo\Model\Carrier\UData;
+use Psr\Log\LoggerInterface;
+use Magento\Store\Model\StoreManagerInterface;
+
+class OrderCreateWebhook implements ObserverInterface
+{
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl; // Initialize the Curl instance
+        $this->storeManager = $storeManager;
+    }
+
+    public function execute(Observer $observer)
+    {
+        $this->logger->info('OrderCreateWebhook: execute method started');
+
+        $order = $observer->getEvent()->getOrder();
+        if (!$order) {
+            $this->logger->error('OrderCreateWebhook: No order object found in observer');
+            return;
+        }
+
+        // Log order creation data
+        $this->logger->info('Order Created:', ['order_id' => $order->getId(), 'order_data' => $order->getData()]);
+
+        // Extract order data and send to the webhook URL
+        $this->sendWebhook($order, 'order_created');
+
+        $this->logger->info('OrderCreateWebhook: execute method finished');
+    }
+
+    private function sendWebhook($order, $eventType)
+    {
+        $this->logger->info('OrderCreateWebhook: sendWebhook method started');
+
+        // Webhook URL
+        $url = $this->getWebhookUrl();
+        $this->logger->info('OrderCreateWebhook: Webhook URL', ['url' => $url]);
+
+        // Get Store UUID and add to query parameters
+        $storeUuid = $this->getStoreUuid();
+        $this->logger->info('UUID: ', ['uuid' => $storeUuid]);
+        $url .= '?channel=' . urlencode($storeUuid);
+        $this->logger->info('Webhook URL', ['url' => $url]);
+
+        // Prepare payload
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'order_data' => $order->getData()
+        ];
+
+        // Log webhook payload
+        $this->logger->info('Sending Webhook:', ['url' => $url, 'payload' => $data]);
+
+        // Send the webhook
+        $this->makeHttpPostRequest($url, $data);
+
+        $this->logger->info('OrderCreateWebhook: sendWebhook method finished');
+    }
+
+
+    private function makeHttpPostRequest($url, $data)
+    {
+        $this->logger->info('URL:', ['url' => $url]);
+        $this->logger->info('Data:', ['data' => $data]);
+
+        // Perform the API request
+        $payloadJson = json_encode($data);
+        if ($payloadJson === false) {
+            $this->logger->error('Payload Webhook failed: Unable to encode JSON.');
+            throw new \RuntimeException('Failed to encode payload to JSON.');
+        }
+
+        $this->logger->info('Payload Webhook:', ['response' => $payloadJson]);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->post($url, $payloadJson);
+        $statusCode = $this->curl->getStatus();
+        $responseBody = $this->curl->getBody();
+
+        // Log status code and response body
+        $this->logger->info('Webhook Response Status:', ['status' => $statusCode]);
+        $this->logger->info('Webhook Response Body:', ['response' => $responseBody]);
+
+        // Decode the response
+        $response = json_decode($responseBody, true);
+        if (json_last_error() !== JSON_ERROR_NONE) {
+            $this->logger->error('Failed to decode webhook response:', ['error' => json_last_error_msg()]);
+        } else {
+            $this->logger->info('Response Webhook:', ['response' => $response]);
+        }
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreUuid(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+        //return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+}
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
new file mode 100644
index 0000000..ad2a4ad
--- /dev/null
+++ b/Observer/OrderUpdateWebhook.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use Magento\Framework\Event\Observer;
+use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use Magento\Store\Model\StoreManagerInterface;
+use BobGroup\BobGo\Model\Carrier\UData;
+use Psr\Log\LoggerInterface;
+
+class OrderUpdateWebhook implements ObserverInterface
+{
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl;
+        $this->storeManager = $storeManager;
+    }
+
+    public function execute(Observer $observer)
+    {
+        $order = $observer->getEvent()->getOrder();
+        if (!$order) {
+            return;
+        }
+
+        $this->sendWebhook($order, 'order_updated');
+    }
+
+    private function sendWebhook($order, $eventType)
+    {
+        $url = $this->getWebhookUrl();
+
+        // Get Store UUID and add to query parameters
+        $storeUuid = $this->getStoreUuid();
+        $url .= '?channel=' . urlencode($storeUuid);
+
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'order_data' => $order->getData()
+        ];
+
+        $this->makeHttpPostRequest($url, $data);
+    }
+
+    private function makeHttpPostRequest($url, $data)
+    {
+        $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);
+        $statusCode = $this->curl->getStatus();
+        $responseBody = $this->curl->getBody();
+
+        $response = json_decode($responseBody, true);
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreUuid(): string
+    {
+        return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+}
diff --git a/etc/events.xml b/etc/events.xml
index bfb5e96..3e71bc3 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -1,3 +1,9 @@
 <?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_order_place_after">
+        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
+    </event>
+    <event name="sales_order_save_after">
+        <observer name="order_update_webhook" instance="BobGroup\BobGo\Observer\OrderUpdateWebhook"/>
+    </event>
 </config>
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
index bc1aaeb..25a80a9 100644
--- a/etc/frontend/di.xml
+++ b/etc/frontend/di.xml
@@ -13,4 +13,12 @@
             <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
         </arguments>
     </type>
+    <type name="BobGroup\BobGo\Observer\OrderCreateWebhook">
+        <arguments>
+            <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
+            <argument name="curl" xsi:type="object">Magento\Framework\HTTP\Client\Curl</argument>
+            <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface</argument>
+        </arguments>
+    </type>
+
 </config>
-- 
GitLab


From 6d003aacf9861dd4bed866e56577e56cce4a0e2f Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 28 Aug 2024 14:18:32 +0200
Subject: [PATCH 02/56] Add to webhooks

---
 Observer/OrderCreateWebhook.php | 78 ++++++++++++++++-----------------
 Observer/OrderUpdateWebhook.php | 52 +++++++++++++++++++---
 2 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index f301cc8..3f29ba7 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -18,91 +18,83 @@ class OrderCreateWebhook implements ObserverInterface
     public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
     {
         $this->logger = $logger;
-        $this->curl = $curl; // Initialize the Curl instance
+        $this->curl = $curl;
         $this->storeManager = $storeManager;
     }
 
     public function execute(Observer $observer)
     {
-        $this->logger->info('OrderCreateWebhook: execute method started');
-
         $order = $observer->getEvent()->getOrder();
         if (!$order) {
-            $this->logger->error('OrderCreateWebhook: No order object found in observer');
+            //$this->logger->error('OrderCreateWebhook: No order object found in observer');
             return;
         }
 
-        // Log order creation data
-        $this->logger->info('Order Created:', ['order_id' => $order->getId(), 'order_data' => $order->getData()]);
-
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_created');
-
-        $this->logger->info('OrderCreateWebhook: execute method finished');
+        $this->sendWebhook($order, 'order_create');
     }
 
     private function sendWebhook($order, $eventType)
     {
-        $this->logger->info('OrderCreateWebhook: sendWebhook method started');
-
         // Webhook URL
         $url = $this->getWebhookUrl();
-        $this->logger->info('OrderCreateWebhook: Webhook URL', ['url' => $url]);
 
-        // Get Store UUID and add to query parameters
-        $storeUuid = $this->getStoreUuid();
-        $this->logger->info('UUID: ', ['uuid' => $storeUuid]);
-        $url .= '?channel=' . urlencode($storeUuid);
-        $this->logger->info('Webhook URL', ['url' => $url]);
+        // Extract order items
+        $itemsData = [];
+        foreach ($order->getAllItems() as $item) {
+            $itemsData[] = $item->getData();
+        }
+
+        // Extract shipping address
+        $shippingAddress = $order->getShippingAddress();
+        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
+
+        // Extract billing address
+        $billingAddress = $order->getBillingAddress();
+        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
-            'order_data' => $order->getData()
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $this->getStoreId(),
+            'order_data' => $order->getData(),
+            'items' => $itemsData,
+            'shipping_address' => $shippingAddressData,
+            'billing_address'  => $billingAddressData,
         ];
 
-        // Log webhook payload
-        $this->logger->info('Sending Webhook:', ['url' => $url, 'payload' => $data]);
-
         // Send the webhook
         $this->makeHttpPostRequest($url, $data);
-
-        $this->logger->info('OrderCreateWebhook: sendWebhook method finished');
     }
 
-
     private function makeHttpPostRequest($url, $data)
     {
-        $this->logger->info('URL:', ['url' => $url]);
-        $this->logger->info('Data:', ['data' => $data]);
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'your_secret_key';
+        $payloadJson = json_encode($data);
+        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->addHeader('X-M-Webhook-Signature', $signature); // Add your custom header here
 
         // Perform the API request
         $payloadJson = json_encode($data);
         if ($payloadJson === false) {
-            $this->logger->error('Payload Webhook failed: Unable to encode JSON.');
+            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
             throw new \RuntimeException('Failed to encode payload to JSON.');
         }
 
-        $this->logger->info('Payload Webhook:', ['response' => $payloadJson]);
-
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
         $statusCode = $this->curl->getStatus();
         $responseBody = $this->curl->getBody();
 
-        // Log status code and response body
-        $this->logger->info('Webhook Response Status:', ['status' => $statusCode]);
-        $this->logger->info('Webhook Response Body:', ['response' => $responseBody]);
-
         // Decode the response
         $response = json_decode($responseBody, true);
-        if (json_last_error() !== JSON_ERROR_NONE) {
-            $this->logger->error('Failed to decode webhook response:', ['error' => json_last_error_msg()]);
-        } else {
-            $this->logger->info('Response Webhook:', ['response' => $response]);
-        }
     }
 
     private function getWebhookUrl(): string
@@ -110,10 +102,14 @@ class OrderCreateWebhook implements ObserverInterface
         return UData::WEBHOOK_URL;
     }
 
-    private function getStoreUuid(): string
+    private function getStoreId(): string
     {
         $storeId = $this->storeManager->getStore()->getId();
         return $storeId;
-        //return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+
+    private function getStoreUrl(): string
+    {
+        return $this->storeManager->getStore()->getBaseUrl();
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index ad2a4ad..6d6b43a 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -5,9 +5,9 @@ namespace BobGroup\BobGo\Observer;
 use Magento\Framework\Event\Observer;
 use Magento\Framework\Event\ObserverInterface;
 use Magento\Framework\HTTP\Client\Curl;
-use Magento\Store\Model\StoreManagerInterface;
 use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
+use Magento\Store\Model\StoreManagerInterface;
 
 class OrderUpdateWebhook implements ObserverInterface
 {
@@ -29,38 +29,70 @@ class OrderUpdateWebhook implements ObserverInterface
             return;
         }
 
+        // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_updated');
     }
 
     private function sendWebhook($order, $eventType)
     {
+        // Webhook URL
         $url = $this->getWebhookUrl();
 
-        // Get Store UUID and add to query parameters
-        $storeUuid = $this->getStoreUuid();
-        $url .= '?channel=' . urlencode($storeUuid);
+        // Extract order items
+        $itemsData = [];
+        foreach ($order->getAllItems() as $item) {
+            $itemsData[] = $item->getData();
+        }
+
+        // Extract shipping address
+        $shippingAddress = $order->getShippingAddress();
+        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
+
+        // Extract billing address
+        $billingAddress = $order->getBillingAddress();
+        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
-            'order_data' => $order->getData()
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $this->getStoreId(),
+            'order_data' => $order->getData(),
+            'items' => $itemsData,
+            'shipping_address' => $shippingAddressData,
+            'billing_address'  => $billingAddressData,
         ];
 
+        // Send the webhook
         $this->makeHttpPostRequest($url, $data);
     }
 
     private function makeHttpPostRequest($url, $data)
     {
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'your_secret_key';
+        $payloadJson = json_encode($data);
+        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->addHeader('X-M-Webhook-Signature', $signature); // Add your custom header here
+
+        // Perform the API request
         $payloadJson = json_encode($data);
         if ($payloadJson === false) {
+            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
             throw new \RuntimeException('Failed to encode payload to JSON.');
         }
 
+        // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
         $statusCode = $this->curl->getStatus();
         $responseBody = $this->curl->getBody();
 
+        // Decode the response
         $response = json_decode($responseBody, true);
     }
 
@@ -69,8 +101,14 @@ class OrderUpdateWebhook implements ObserverInterface
         return UData::WEBHOOK_URL;
     }
 
-    private function getStoreUuid(): string
+    private function getStoreId(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+    }
+
+    private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+        return $this->storeManager->getStore()->getBaseUrl();
     }
 }
-- 
GitLab


From 4b9bbb9fa1cadabdd6ed70d30f4145748981bc04 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 08:14:04 +0200
Subject: [PATCH 03/56] Clean identifier url

---
 Observer/OrderCreateWebhook.php | 18 +++++++++++++++++-
 Observer/OrderUpdateWebhook.php | 18 +++++++++++++++++-
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 3f29ba7..010bec5 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -110,6 +110,22 @@ class OrderCreateWebhook implements ObserverInterface
 
     private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getBaseUrl();
+        $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;
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 6d6b43a..01b7695 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -109,6 +109,22 @@ class OrderUpdateWebhook implements ObserverInterface
 
     private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getBaseUrl();
+        $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;
     }
 }
-- 
GitLab


From 10570227e1bf7bf6f77e469f93733229d53ebf50 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 10:55:10 +0200
Subject: [PATCH 04/56] webhook signature

---
 Observer/OrderCreateWebhook.php | 28 +++++++++++++++++-----------
 Observer/OrderUpdateWebhook.php | 25 +++++++++++++++----------
 2 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 010bec5..cf90443 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -31,7 +31,7 @@ class OrderCreateWebhook implements ObserverInterface
         }
 
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_create');
+        $this->sendWebhook($order, 'order_created');
     }
 
     private function sendWebhook($order, $eventType)
@@ -53,28 +53,34 @@ class OrderCreateWebhook implements ObserverInterface
         $billingAddress = $order->getBillingAddress();
         $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        $storeId = $this->getStoreId();
+
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
             'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $this->getStoreId(),
-            'order_data' => $order->getData(),
-            'items' => $itemsData,
-            'shipping_address' => $shippingAddressData,
-            'billing_address'  => $billingAddressData,
+            'store_id' => $storeId,
+            //'order_data' => $order->getData(),
+            //'items' => $itemsData,
+            //'shipping_address' => $shippingAddressData,
+            //'billing_address'  => $billingAddressData,
         ];
 
         // Send the webhook
-        $this->makeHttpPostRequest($url, $data);
+        $this->makeHttpPostRequest($url, $data, $storeId);
     }
 
-    private function makeHttpPostRequest($url, $data)
+    private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'your_secret_key';
-        $payloadJson = json_encode($data);
-        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+
+        // Encode the binary data in Base64
+        $signature = base64_encode($rawSignature);
+
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 01b7695..095c887 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -52,28 +52,33 @@ class OrderUpdateWebhook implements ObserverInterface
         $billingAddress = $order->getBillingAddress();
         $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        $storeId = $this->getStoreId();
+
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
             'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $this->getStoreId(),
-            'order_data' => $order->getData(),
-            'items' => $itemsData,
-            'shipping_address' => $shippingAddressData,
-            'billing_address'  => $billingAddressData,
+            'store_id' => $storeId,
+            //'order_data' => $order->getData(),
+            //'items' => $itemsData,
+            //'shipping_address' => $shippingAddressData,
+            //'billing_address'  => $billingAddressData,
         ];
 
         // Send the webhook
-        $this->makeHttpPostRequest($url, $data);
+        $this->makeHttpPostRequest($url, $data, $storeId);
     }
 
-    private function makeHttpPostRequest($url, $data)
+    private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'your_secret_key';
-        $payloadJson = json_encode($data);
-        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+
+        // Encode the binary data in Base64
+        $signature = base64_encode($rawSignature);
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
-- 
GitLab


From 716ecb04b0759c92c01b801f33af34182209e837 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 11:46:53 +0200
Subject: [PATCH 05/56] use sahred functions for webhooks

---
 Observer/OrderCreateWebhook.php | 104 +-------------------------------
 Observer/OrderUpdateWebhook.php | 102 +------------------------------
 Observer/OrderWebhookBase.php   |  85 ++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 204 deletions(-)
 create mode 100644 Observer/OrderWebhookBase.php

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index cf90443..1b93779 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -9,7 +9,7 @@ use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
-class OrderCreateWebhook implements ObserverInterface
+class OrderCreateWebhook extends OrderWebhookBase
 {
     protected Curl $curl;
     protected LoggerInterface $logger;
@@ -26,112 +26,10 @@ class OrderCreateWebhook implements ObserverInterface
     {
         $order = $observer->getEvent()->getOrder();
         if (!$order) {
-            //$this->logger->error('OrderCreateWebhook: No order object found in observer');
             return;
         }
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_created');
     }
-
-    private function sendWebhook($order, $eventType)
-    {
-        // Webhook URL
-        $url = $this->getWebhookUrl();
-
-        // Extract order items
-        $itemsData = [];
-        foreach ($order->getAllItems() as $item) {
-            $itemsData[] = $item->getData();
-        }
-
-        // Extract shipping address
-        $shippingAddress = $order->getShippingAddress();
-        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
-
-        // Extract billing address
-        $billingAddress = $order->getBillingAddress();
-        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
-
-        $storeId = $this->getStoreId();
-
-        // Prepare payload
-        $data = [
-            'event' => $eventType,
-            'order_id' => $order->getId(),
-            'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $storeId,
-            //'order_data' => $order->getData(),
-            //'items' => $itemsData,
-            //'shipping_address' => $shippingAddressData,
-            //'billing_address'  => $billingAddressData,
-        ];
-
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
-        // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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); // Add your custom header here
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
-        $statusCode = $this->curl->getStatus();
-        $responseBody = $this->curl->getBody();
-
-        // Decode the response
-        $response = json_decode($responseBody, true);
-    }
-
-    private function getWebhookUrl(): string
-    {
-        return UData::WEBHOOK_URL;
-    }
-
-    private function getStoreId(): string
-    {
-        $storeId = $this->storeManager->getStore()->getId();
-        return $storeId;
-    }
-
-    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;
-    }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 095c887..03b96cb 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -9,7 +9,7 @@ use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
-class OrderUpdateWebhook implements ObserverInterface
+class OrderUpdateWebhook extends OrderWebhookBase
 {
     protected Curl $curl;
     protected LoggerInterface $logger;
@@ -32,104 +32,4 @@ class OrderUpdateWebhook implements ObserverInterface
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_updated');
     }
-
-    private function sendWebhook($order, $eventType)
-    {
-        // Webhook URL
-        $url = $this->getWebhookUrl();
-
-        // Extract order items
-        $itemsData = [];
-        foreach ($order->getAllItems() as $item) {
-            $itemsData[] = $item->getData();
-        }
-
-        // Extract shipping address
-        $shippingAddress = $order->getShippingAddress();
-        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
-
-        // Extract billing address
-        $billingAddress = $order->getBillingAddress();
-        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
-
-        $storeId = $this->getStoreId();
-
-        // Prepare payload
-        $data = [
-            'event' => $eventType,
-            'order_id' => $order->getId(),
-            'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $storeId,
-            //'order_data' => $order->getData(),
-            //'items' => $itemsData,
-            //'shipping_address' => $shippingAddressData,
-            //'billing_address'  => $billingAddressData,
-        ];
-
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
-        // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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); // Add your custom header here
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
-        $statusCode = $this->curl->getStatus();
-        $responseBody = $this->curl->getBody();
-
-        // Decode the response
-        $response = json_decode($responseBody, true);
-    }
-
-    private function getWebhookUrl(): string
-    {
-        return UData::WEBHOOK_URL;
-    }
-
-    private function getStoreId(): string
-    {
-        $storeId = $this->storeManager->getStore()->getId();
-        return $storeId;
-    }
-
-    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;
-    }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
new file mode 100644
index 0000000..9f2e83f
--- /dev/null
+++ b/Observer/OrderWebhookBase.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use BobGroup\BobGo\Model\Carrier\UData;
+use Magento\Framework\Event\ObserverInterface;
+
+abstract class OrderWebhookBase implements ObserverInterface
+{
+    protected function sendWebhook($order, $eventType)
+    {
+        // Webhook URL
+        $url = $this->getWebhookUrl();
+
+        $storeId = $this->getStoreId();
+
+        // Prepare payload
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $storeId,
+        ];
+
+        // Send the webhook
+        $this->makeHttpPostRequest($url, $data, $storeId);
+    }
+
+    private function makeHttpPostRequest($url, $data, $storeId)
+    {
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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);
+
+        // Perform the API request
+        $payloadJson = json_encode($data);
+        if ($payloadJson === false) {
+            throw new \RuntimeException('Failed to encode payload to JSON.');
+        }
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->post($url, $payloadJson);
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreId(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+    }
+
+    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;
+    }
+}
-- 
GitLab


From 9d91f05abd105839cda7e36e85312fca08884a49 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 12:00:12 +0200
Subject: [PATCH 06/56] cleanup

---
 Observer/OrderCreateWebhook.php | 16 ----------------
 Observer/OrderUpdateWebhook.php | 16 ----------------
 Observer/OrderWebhookBase.php   | 14 ++++++++++++++
 3 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 1b93779..678f2de 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -3,25 +3,9 @@
 namespace BobGroup\BobGo\Observer;
 
 use Magento\Framework\Event\Observer;
-use Magento\Framework\Event\ObserverInterface;
-use Magento\Framework\HTTP\Client\Curl;
-use BobGroup\BobGo\Model\Carrier\UData;
-use Psr\Log\LoggerInterface;
-use Magento\Store\Model\StoreManagerInterface;
 
 class OrderCreateWebhook extends OrderWebhookBase
 {
-    protected Curl $curl;
-    protected LoggerInterface $logger;
-    protected StoreManagerInterface $storeManager;
-
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
-    {
-        $this->logger = $logger;
-        $this->curl = $curl;
-        $this->storeManager = $storeManager;
-    }
-
     public function execute(Observer $observer)
     {
         $order = $observer->getEvent()->getOrder();
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 03b96cb..3074bdd 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -3,25 +3,9 @@
 namespace BobGroup\BobGo\Observer;
 
 use Magento\Framework\Event\Observer;
-use Magento\Framework\Event\ObserverInterface;
-use Magento\Framework\HTTP\Client\Curl;
-use BobGroup\BobGo\Model\Carrier\UData;
-use Psr\Log\LoggerInterface;
-use Magento\Store\Model\StoreManagerInterface;
 
 class OrderUpdateWebhook extends OrderWebhookBase
 {
-    protected Curl $curl;
-    protected LoggerInterface $logger;
-    protected StoreManagerInterface $storeManager;
-
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
-    {
-        $this->logger = $logger;
-        $this->curl = $curl;
-        $this->storeManager = $storeManager;
-    }
-
     public function execute(Observer $observer)
     {
         $order = $observer->getEvent()->getOrder();
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 9f2e83f..b17375e 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -4,9 +4,23 @@ namespace BobGroup\BobGo\Observer;
 
 use BobGroup\BobGo\Model\Carrier\UData;
 use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use Magento\Store\Model\StoreManagerInterface;
+use Psr\Log\LoggerInterface;
 
 abstract class OrderWebhookBase implements ObserverInterface
 {
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl;
+        $this->storeManager = $storeManager;
+    }
+
     protected function sendWebhook($order, $eventType)
     {
         // Webhook URL
-- 
GitLab


From 2c7e23cd114945e40000eb3c0ded52295faadfab Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 14:57:11 +0200
Subject: [PATCH 07/56] orderId for both created and updated

---
 Observer/OrderCreateWebhook.php |  2 +-
 Observer/OrderUpdateWebhook.php | 19 -------------------
 Observer/OrderWebhookBase.php   | 23 +++++++++++++++++++++--
 etc/events.xml                  |  5 +----
 4 files changed, 23 insertions(+), 26 deletions(-)
 delete mode 100644 Observer/OrderUpdateWebhook.php

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 678f2de..74f1ce4 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -14,6 +14,6 @@ class OrderCreateWebhook extends OrderWebhookBase
         }
 
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_created');
+        $this->sendWebhook($order);
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
deleted file mode 100644
index 3074bdd..0000000
--- a/Observer/OrderUpdateWebhook.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-namespace BobGroup\BobGo\Observer;
-
-use Magento\Framework\Event\Observer;
-
-class OrderUpdateWebhook 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, 'order_updated');
-    }
-}
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index b17375e..f4ca74d 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -21,17 +21,36 @@ abstract class OrderWebhookBase implements ObserverInterface
         $this->storeManager = $storeManager;
     }
 
-    protected function sendWebhook($order, $eventType)
+    protected function sendWebhook($order)
     {
         // Webhook URL
         $url = $this->getWebhookUrl();
 
         $storeId = $this->getStoreId();
 
+        $orderId = $order->getId();
+
+        // Get the order creation time
+        $createdAt = strtotime($order->getCreatedAt());
+        $currentTime = time();
+
+        // Define a time threshold  to consider the order as newly created
+        $threshold = 5; // 5  seconds
+
+        // Determine the event type based on the creation time
+        if (($currentTime - $createdAt) < $threshold) {
+            $eventType = 'order_created';
+        } else {
+            $eventType = 'order_updated';
+        }
+
+        // Log the event type for debugging purposes
+        $this->logger->info('event: ' . $eventType);
+
         // Prepare payload
         $data = [
             'event' => $eventType,
-            'order_id' => $order->getId(),
+            'order_id' => $orderId,
             'channel_identifier' => $this->getStoreUrl(),
             'store_id' => $storeId,
         ];
diff --git a/etc/events.xml b/etc/events.xml
index 3e71bc3..d4d14f1 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -1,9 +1,6 @@
 <?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_order_place_after">
-        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
-    </event>
     <event name="sales_order_save_after">
-        <observer name="order_update_webhook" instance="BobGroup\BobGo\Observer\OrderUpdateWebhook"/>
+        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
     </event>
 </config>
-- 
GitLab


From bb9b08a1e575ba35c1c73d2fe254969d6d6b1af6 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 14:58:47 +0200
Subject: [PATCH 08/56] cleanup

---
 Observer/OrderWebhookBase.php | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index f4ca74d..eeb106e 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -44,9 +44,6 @@ abstract class OrderWebhookBase implements ObserverInterface
             $eventType = 'order_updated';
         }
 
-        // Log the event type for debugging purposes
-        $this->logger->info('event: ' . $eventType);
-
         // Prepare payload
         $data = [
             'event' => $eventType,
-- 
GitLab


From 366c40ca7cb2693fa52b45e0195be818cb6385d1 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 15:08:50 +0200
Subject: [PATCH 09/56] change endpoint

---
 Model/Carrier/UData.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index a7e5d2e..adf83a2 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
 }
-- 
GitLab


From 0a4fe2d80feadc91b8296bc610ca400d07b75a51 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Fri, 30 Aug 2024 15:00:54 +0200
Subject: [PATCH 10/56] start implementation

---
 Block/TrackOrder.php                          | 18 ++++++++++
 Controller/Test/Index.php                     | 20 +++++++++++
 Controller/TrackOrder/Index.php               | 33 +++++++++++++++++++
 etc/adminhtml/system.xml                      |  6 ++++
 etc/frontend/routes.xml                       |  7 ++++
 .../layout/bobgo_trackorder_index.xml         | 14 ++++++++
 view/frontend/layout/customer_account.xml     | 20 +++++++++++
 .../frontend/templates/TrackOrder/index.phtml |  5 +++
 8 files changed, 123 insertions(+)
 create mode 100644 Block/TrackOrder.php
 create mode 100644 Controller/Test/Index.php
 create mode 100644 Controller/TrackOrder/Index.php
 create mode 100644 etc/frontend/routes.xml
 create mode 100644 view/frontend/layout/bobgo_trackorder_index.xml
 create mode 100644 view/frontend/layout/customer_account.xml
 create mode 100644 view/frontend/templates/TrackOrder/index.phtml

diff --git a/Block/TrackOrder.php b/Block/TrackOrder.php
new file mode 100644
index 0000000..49983f6
--- /dev/null
+++ b/Block/TrackOrder.php
@@ -0,0 +1,18 @@
+<?php
+namespace BobGroup\BobGo\Block;
+class TrackOrder extends \Magento\Framework\View\Element\Template
+{
+    public function __construct(
+        \Magento\Backend\Block\Template\Context $context,
+        array $data = []
+    )
+    {
+        parent::__construct($context, $data);
+    }
+
+    public function getHelloWorld()
+    {
+        return 'Hello World';
+    }
+
+}
diff --git a/Controller/Test/Index.php b/Controller/Test/Index.php
new file mode 100644
index 0000000..115b950
--- /dev/null
+++ b/Controller/Test/Index.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace BobGroup\BobGo\Controller\Test;
+
+use Magento\Framework\App\Action\Action;
+use Magento\Framework\App\Action\Context;
+
+class Index extends Action
+{
+    public function __construct(Context $context)
+    {
+        parent::__construct($context);
+    }
+
+    public function execute()
+    {
+        echo "Test controller works!";
+        exit;
+    }
+}
diff --git a/Controller/TrackOrder/Index.php b/Controller/TrackOrder/Index.php
new file mode 100644
index 0000000..0810484
--- /dev/null
+++ b/Controller/TrackOrder/Index.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace BobGroup\BobGo\Controller\TrackOrder;
+
+class Index extends \Magento\Framework\App\Action\Action
+{
+    /**
+     * @var \Magento\Framework\View\Result\PageFactory
+     */
+    protected $resultPageFactory;
+
+    /**
+     * @param \Magento\Framework\App\Action\Context $context
+     * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
+     */
+    public function __construct(
+        \Magento\Framework\App\Action\Context $context,
+        \Magento\Framework\View\Result\PageFactory $resultPageFactory
+    )
+    {
+        $this->resultPageFactory = $resultPageFactory;
+        parent::__construct($context);
+    }
+    /**
+     * Default customer account page
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        return $this->resultPageFactory->create();
+    }
+}
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 410c2c2..263bc8b 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -28,7 +28,13 @@
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                     <comment>Displays the delivery timeframe and additional service level description, as configured on Bob Go.</comment>
                 </field>
+                    <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
+                        <label>Enable Track My Order</label>
+                        <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
+                        <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                    </field>
             </group>
         </section>
+
     </system>
 </config>
diff --git a/etc/frontend/routes.xml b/etc/frontend/routes.xml
new file mode 100644
index 0000000..e0d84f8
--- /dev/null
+++ b/etc/frontend/routes.xml
@@ -0,0 +1,7 @@
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
+    <router id="standard">
+        <route id="trackorder" frontName="trackorder">
+            <module name="BobGroup_BobGo" />
+        </route>
+    </router>
+</config>
diff --git a/view/frontend/layout/bobgo_trackorder_index.xml b/view/frontend/layout/bobgo_trackorder_index.xml
new file mode 100644
index 0000000..91e4a80
--- /dev/null
+++ b/view/frontend/layout/bobgo_trackorder_index.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
+<update handle="customer_account"/>
+<head>
+    <title>
+        Your First Link
+    </title>
+</head>
+<body>
+    <referenceContainer name="content">
+        <block class="BobGroup\BobGo\Block\TrackOrder" name="bobgo.trackorder.index" template="BobGroup_BobGo::trackorder/index.phtml" cacheable="false" />
+    </referenceContainer>
+</body>
+</page>
diff --git a/view/frontend/layout/customer_account.xml b/view/frontend/layout/customer_account.xml
new file mode 100644
index 0000000..50bb287
--- /dev/null
+++ b/view/frontend/layout/customer_account.xml
@@ -0,0 +1,20 @@
+<?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="customer_account_navigation">
+            <!-- Add menu to the end of the sidebar -->
+            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
+                <arguments>
+                    <argument name="path" xsi:type="string">BobGo/TrackOrder/index</argument>
+                    <argument name="label" xsi:type="string">Your First Link</argument>
+                </arguments>
+            </block>
+            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
+                <arguments>
+                    <argument name="path" xsi:type="string">BobGo/TrackOrder/index</argument>
+                    <argument name="label" xsi:type="string">Your Second Link</argument>
+                </arguments>
+            </block>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/view/frontend/templates/TrackOrder/index.phtml b/view/frontend/templates/TrackOrder/index.phtml
new file mode 100644
index 0000000..8c81e6b
--- /dev/null
+++ b/view/frontend/templates/TrackOrder/index.phtml
@@ -0,0 +1,5 @@
+<h2>
+    <?php echo $block->getHelloWorld(); ?>
+</h2>
+
+echo 'My First Link Page';
-- 
GitLab


From 61a9c3d101c0dbdefa85d959141d0d684dc69f34 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 2 Sep 2024 10:31:31 +0200
Subject: [PATCH 11/56] page link working

---
 Block/System/Config/Form/Field/Version.php    | 66 -------------------
 Block/{TrackOrder.php => YourBlock.php}       |  2 +-
 Controller/Test/Index.php                     | 20 ------
 .../{TrackOrder => YourFirstLink}/Index.php   |  8 ++-
 Controller/YourSecondLink/Index.php           | 38 +++++++++++
 etc/frontend/routes.xml                       |  4 +-
 .../layout/bobgo_trackorder_index.xml         | 14 ----
 .../layout/bobgo_yourfirstlink_index.xml      | 14 ++++
 .../layout/bobgo_yoursecondlink_index.xml     | 14 ++++
 view/frontend/layout/customer_account.xml     | 34 +++++-----
 .../frontend/templates/secondlink/index.phtml |  1 +
 .../{TrackOrder => yourfirstlink}/index.phtml |  0
 12 files changed, 95 insertions(+), 120 deletions(-)
 delete mode 100644 Block/System/Config/Form/Field/Version.php
 rename Block/{TrackOrder.php => YourBlock.php} (82%)
 delete mode 100644 Controller/Test/Index.php
 rename Controller/{TrackOrder => YourFirstLink}/Index.php (76%)
 create mode 100644 Controller/YourSecondLink/Index.php
 delete mode 100644 view/frontend/layout/bobgo_trackorder_index.xml
 create mode 100644 view/frontend/layout/bobgo_yourfirstlink_index.xml
 create mode 100644 view/frontend/layout/bobgo_yoursecondlink_index.xml
 create mode 100644 view/frontend/templates/secondlink/index.phtml
 rename view/frontend/templates/{TrackOrder => yourfirstlink}/index.phtml (100%)

diff --git a/Block/System/Config/Form/Field/Version.php b/Block/System/Config/Form/Field/Version.php
deleted file mode 100644
index 2ebcbba..0000000
--- a/Block/System/Config/Form/Field/Version.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-namespace BobGroup\BobGo\Block\System\Config\Form\Field;
-
-use Magento\Framework\Data\Form\Element\AbstractElement;
-use BobGroup\BobGo\Helper\Data;
-
-/**
- * Displays Version number in System Configuration
- *
- * This block is responsible for displaying the version number of the BobGo extension
- * in the system configuration settings.
- *
- * @website https://www.bobgo.co.za
- */
-class Version extends \Magento\Config\Block\System\Config\Form\Field
-{
-    /**
-     * @var string
-     */
-    public const EXTENSION_URL = 'https://www.bobgo.co.za';
-
-    /**
-     * @var Data
-     */
-    protected Data $_helper;
-
-    /**
-     * Constructor
-     *
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param Data $helper
-     */
-    public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        Data $helper
-    ) {
-        $this->_helper = $helper;
-        parent::__construct($context);
-    }
-
-    /**
-     * Get HTML for the element
-     *
-     * @param AbstractElement $element
-     * @return string
-     */
-    protected function _getElementHtml(AbstractElement $element): string
-    {
-        $extensionVersion = $this->_helper->getExtensionVersion();
-        $extensionTitle = 'BobGo';
-        $versionLabel = sprintf(
-            '<a href="%s" title="%s" target="_blank">%s</a>',
-            self::EXTENSION_URL,
-            $extensionTitle,
-            $extensionVersion
-        );
-
-        // Set the value using setData
-        $element->setData('value', $versionLabel);
-
-        // Ensure the return value is a string or provide a fallback
-        $value = $element->getData('value');
-        return is_string($value) ? $value : '';
-    }
-}
diff --git a/Block/TrackOrder.php b/Block/YourBlock.php
similarity index 82%
rename from Block/TrackOrder.php
rename to Block/YourBlock.php
index 49983f6..c3e7e01 100644
--- a/Block/TrackOrder.php
+++ b/Block/YourBlock.php
@@ -1,6 +1,6 @@
 <?php
 namespace BobGroup\BobGo\Block;
-class TrackOrder extends \Magento\Framework\View\Element\Template
+class YourBlock extends \Magento\Framework\View\Element\Template
 {
     public function __construct(
         \Magento\Backend\Block\Template\Context $context,
diff --git a/Controller/Test/Index.php b/Controller/Test/Index.php
deleted file mode 100644
index 115b950..0000000
--- a/Controller/Test/Index.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-namespace BobGroup\BobGo\Controller\Test;
-
-use Magento\Framework\App\Action\Action;
-use Magento\Framework\App\Action\Context;
-
-class Index extends Action
-{
-    public function __construct(Context $context)
-    {
-        parent::__construct($context);
-    }
-
-    public function execute()
-    {
-        echo "Test controller works!";
-        exit;
-    }
-}
diff --git a/Controller/TrackOrder/Index.php b/Controller/YourFirstLink/Index.php
similarity index 76%
rename from Controller/TrackOrder/Index.php
rename to Controller/YourFirstLink/Index.php
index 0810484..51781bc 100644
--- a/Controller/TrackOrder/Index.php
+++ b/Controller/YourFirstLink/Index.php
@@ -1,6 +1,7 @@
 <?php
+namespace BobGroup\BobGo\Controller\YourFirstLink;
 
-namespace BobGroup\BobGo\Controller\TrackOrder;
+use Psr\Log\LoggerInterface;
 
 class Index extends \Magento\Framework\App\Action\Action
 {
@@ -9,16 +10,20 @@ class Index extends \Magento\Framework\App\Action\Action
      */
     protected $resultPageFactory;
 
+    protected $logger;
+
     /**
      * @param \Magento\Framework\App\Action\Context $context
      * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
      */
     public function __construct(
         \Magento\Framework\App\Action\Context $context,
+        LoggerInterface $logger,
         \Magento\Framework\View\Result\PageFactory $resultPageFactory
     )
     {
         $this->resultPageFactory = $resultPageFactory;
+        $this->logger = $logger;
         parent::__construct($context);
     }
     /**
@@ -28,6 +33,7 @@ class Index extends \Magento\Framework\App\Action\Action
      */
     public function execute()
     {
+        $this->logger->info('Page Controller is executed.');
         return $this->resultPageFactory->create();
     }
 }
diff --git a/Controller/YourSecondLink/Index.php b/Controller/YourSecondLink/Index.php
new file mode 100644
index 0000000..be38312
--- /dev/null
+++ b/Controller/YourSecondLink/Index.php
@@ -0,0 +1,38 @@
+<?php
+namespace BobGroup\BobGo\Controller\YourSecondLink;
+
+use Psr\Log\LoggerInterface;
+class Index extends \Magento\Framework\App\Action\Action
+{
+    /**
+     * @var \Magento\Framework\View\Result\PageFactory
+     */
+    protected $resultPageFactory;
+
+    protected $logger;
+
+    /**
+     * @param \Magento\Framework\App\Action\Context $context
+     * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
+     */
+    public function __construct(
+        \Magento\Framework\App\Action\Context $context,
+        LoggerInterface $logger,
+        \Magento\Framework\View\Result\PageFactory $resultPageFactory
+    )
+    {
+        $this->resultPageFactory = $resultPageFactory;
+        $this->logger = $logger;
+        parent::__construct($context);
+    }
+    /**
+     * Default customer account page
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        $this->logger->info('Page2 Controller is executed.');
+        return $this->resultPageFactory->create();
+    }
+}
diff --git a/etc/frontend/routes.xml b/etc/frontend/routes.xml
index e0d84f8..d6d1046 100644
--- a/etc/frontend/routes.xml
+++ b/etc/frontend/routes.xml
@@ -1,6 +1,8 @@
+<?xml version="1.0"?>
+
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
     <router id="standard">
-        <route id="trackorder" frontName="trackorder">
+        <route id="bobgo" frontName="bobgo">
             <module name="BobGroup_BobGo" />
         </route>
     </router>
diff --git a/view/frontend/layout/bobgo_trackorder_index.xml b/view/frontend/layout/bobgo_trackorder_index.xml
deleted file mode 100644
index 91e4a80..0000000
--- a/view/frontend/layout/bobgo_trackorder_index.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
-<update handle="customer_account"/>
-<head>
-    <title>
-        Your First Link
-    </title>
-</head>
-<body>
-    <referenceContainer name="content">
-        <block class="BobGroup\BobGo\Block\TrackOrder" name="bobgo.trackorder.index" template="BobGroup_BobGo::trackorder/index.phtml" cacheable="false" />
-    </referenceContainer>
-</body>
-</page>
diff --git a/view/frontend/layout/bobgo_yourfirstlink_index.xml b/view/frontend/layout/bobgo_yourfirstlink_index.xml
new file mode 100644
index 0000000..f5178ae
--- /dev/null
+++ b/view/frontend/layout/bobgo_yourfirstlink_index.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
+    <update handle="customer_account"/>
+    <head>
+        <title>
+            Your First Link
+        </title>
+    </head>
+    <body>
+        <referenceContainer name="content">
+            <block class="BobGroup\BobGo\Block\YourBlock" name="bobgo.firstlink.index" template="BobGroup_BobGo::yourfirstlink/index.phtml" cacheable="false" />
+        </referenceContainer>
+    </body>
+</page>
diff --git a/view/frontend/layout/bobgo_yoursecondlink_index.xml b/view/frontend/layout/bobgo_yoursecondlink_index.xml
new file mode 100644
index 0000000..d456381
--- /dev/null
+++ b/view/frontend/layout/bobgo_yoursecondlink_index.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
+    <update handle="customer_account"/>
+    <head>
+        <title>
+            Your Second Link
+        </title>
+    </head>
+    <body>
+        <referenceContainer name="content">
+            <block class="Magento\Framework\View\Element\Template" name="bobgo.secondlink.index" template="BobGroup_BobGo::yoursecondlink/index.phtml" cacheable="false" />
+        </referenceContainer>
+    </body>
+</page>
diff --git a/view/frontend/layout/customer_account.xml b/view/frontend/layout/customer_account.xml
index 50bb287..cdc2464 100644
--- a/view/frontend/layout/customer_account.xml
+++ b/view/frontend/layout/customer_account.xml
@@ -1,20 +1,20 @@
 <?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="customer_account_navigation">
-            <!-- Add menu to the end of the sidebar -->
-            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
-                <arguments>
-                    <argument name="path" xsi:type="string">BobGo/TrackOrder/index</argument>
-                    <argument name="label" xsi:type="string">Your First Link</argument>
-                </arguments>
-            </block>
-            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
-                <arguments>
-                    <argument name="path" xsi:type="string">BobGo/TrackOrder/index</argument>
-                    <argument name="label" xsi:type="string">Your Second Link</argument>
-                </arguments>
-            </block>
-        </referenceBlock>
-    </body>
+<body>
+    <referenceBlock name="customer_account_navigation">
+        <!-- Add menu to the end of the sidebar -->
+        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
+            <arguments>
+                <argument name="path" xsi:type="string">bobgo/yourfirstlink/index</argument>
+                <argument name="label" xsi:type="string">Your First Link</argument>
+            </arguments>
+        </block>
+        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
+            <arguments>
+                <argument name="path" xsi:type="string">bobgo/yoursecondlink/index</argument>
+                <argument name="label" xsi:type="string">Your Second Link</argument>
+            </arguments>
+        </block>
+    </referenceBlock>
+</body>
 </page>
diff --git a/view/frontend/templates/secondlink/index.phtml b/view/frontend/templates/secondlink/index.phtml
new file mode 100644
index 0000000..c19dc87
--- /dev/null
+++ b/view/frontend/templates/secondlink/index.phtml
@@ -0,0 +1 @@
+echo 'My Second Link Page';
diff --git a/view/frontend/templates/TrackOrder/index.phtml b/view/frontend/templates/yourfirstlink/index.phtml
similarity index 100%
rename from view/frontend/templates/TrackOrder/index.phtml
rename to view/frontend/templates/yourfirstlink/index.phtml
-- 
GitLab


From 0b51db24a80dee63d1bc28eafa2be2775807cdef Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 2 Sep 2024 10:41:33 +0200
Subject: [PATCH 12/56] tracking page link working

---
 Block/{YourBlock.php => TrackingBlock.php}    |  2 +-
 .../{YourFirstLink => Tracking}/Index.php     |  2 +-
 Controller/YourSecondLink/Index.php           | 38 -------------------
 ...ink_index.xml => bobgo_tracking_index.xml} |  4 +-
 .../layout/bobgo_yoursecondlink_index.xml     | 14 -------
 view/frontend/layout/customer_account.xml     | 12 ++----
 .../frontend/templates/secondlink/index.phtml |  1 -
 .../{yourfirstlink => tracking}/index.phtml   |  0
 8 files changed, 7 insertions(+), 66 deletions(-)
 rename Block/{YourBlock.php => TrackingBlock.php} (81%)
 rename Controller/{YourFirstLink => Tracking}/Index.php (94%)
 delete mode 100644 Controller/YourSecondLink/Index.php
 rename view/frontend/layout/{bobgo_yourfirstlink_index.xml => bobgo_tracking_index.xml} (67%)
 delete mode 100644 view/frontend/layout/bobgo_yoursecondlink_index.xml
 delete mode 100644 view/frontend/templates/secondlink/index.phtml
 rename view/frontend/templates/{yourfirstlink => tracking}/index.phtml (100%)

diff --git a/Block/YourBlock.php b/Block/TrackingBlock.php
similarity index 81%
rename from Block/YourBlock.php
rename to Block/TrackingBlock.php
index c3e7e01..f77dab0 100644
--- a/Block/YourBlock.php
+++ b/Block/TrackingBlock.php
@@ -1,6 +1,6 @@
 <?php
 namespace BobGroup\BobGo\Block;
-class YourBlock extends \Magento\Framework\View\Element\Template
+class TrackingBlock extends \Magento\Framework\View\Element\Template
 {
     public function __construct(
         \Magento\Backend\Block\Template\Context $context,
diff --git a/Controller/YourFirstLink/Index.php b/Controller/Tracking/Index.php
similarity index 94%
rename from Controller/YourFirstLink/Index.php
rename to Controller/Tracking/Index.php
index 51781bc..9955e8d 100644
--- a/Controller/YourFirstLink/Index.php
+++ b/Controller/Tracking/Index.php
@@ -1,5 +1,5 @@
 <?php
-namespace BobGroup\BobGo\Controller\YourFirstLink;
+namespace BobGroup\BobGo\Controller\Tracking;
 
 use Psr\Log\LoggerInterface;
 
diff --git a/Controller/YourSecondLink/Index.php b/Controller/YourSecondLink/Index.php
deleted file mode 100644
index be38312..0000000
--- a/Controller/YourSecondLink/Index.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-namespace BobGroup\BobGo\Controller\YourSecondLink;
-
-use Psr\Log\LoggerInterface;
-class Index extends \Magento\Framework\App\Action\Action
-{
-    /**
-     * @var \Magento\Framework\View\Result\PageFactory
-     */
-    protected $resultPageFactory;
-
-    protected $logger;
-
-    /**
-     * @param \Magento\Framework\App\Action\Context $context
-     * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
-     */
-    public function __construct(
-        \Magento\Framework\App\Action\Context $context,
-        LoggerInterface $logger,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory
-    )
-    {
-        $this->resultPageFactory = $resultPageFactory;
-        $this->logger = $logger;
-        parent::__construct($context);
-    }
-    /**
-     * Default customer account page
-     *
-     * @return void
-     */
-    public function execute()
-    {
-        $this->logger->info('Page2 Controller is executed.');
-        return $this->resultPageFactory->create();
-    }
-}
diff --git a/view/frontend/layout/bobgo_yourfirstlink_index.xml b/view/frontend/layout/bobgo_tracking_index.xml
similarity index 67%
rename from view/frontend/layout/bobgo_yourfirstlink_index.xml
rename to view/frontend/layout/bobgo_tracking_index.xml
index f5178ae..6e842d7 100644
--- a/view/frontend/layout/bobgo_yourfirstlink_index.xml
+++ b/view/frontend/layout/bobgo_tracking_index.xml
@@ -3,12 +3,12 @@
     <update handle="customer_account"/>
     <head>
         <title>
-            Your First Link
+            Tracking
         </title>
     </head>
     <body>
         <referenceContainer name="content">
-            <block class="BobGroup\BobGo\Block\YourBlock" name="bobgo.firstlink.index" template="BobGroup_BobGo::yourfirstlink/index.phtml" cacheable="false" />
+            <block class="BobGroup\BobGo\Block\TrackingBlock" name="bobgo.tracking.index" template="BobGroup_BobGo::tracking/index.phtml" cacheable="false" />
         </referenceContainer>
     </body>
 </page>
diff --git a/view/frontend/layout/bobgo_yoursecondlink_index.xml b/view/frontend/layout/bobgo_yoursecondlink_index.xml
deleted file mode 100644
index d456381..0000000
--- a/view/frontend/layout/bobgo_yoursecondlink_index.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
-    <update handle="customer_account"/>
-    <head>
-        <title>
-            Your Second Link
-        </title>
-    </head>
-    <body>
-        <referenceContainer name="content">
-            <block class="Magento\Framework\View\Element\Template" name="bobgo.secondlink.index" template="BobGroup_BobGo::yoursecondlink/index.phtml" cacheable="false" />
-        </referenceContainer>
-    </body>
-</page>
diff --git a/view/frontend/layout/customer_account.xml b/view/frontend/layout/customer_account.xml
index cdc2464..54c3c21 100644
--- a/view/frontend/layout/customer_account.xml
+++ b/view/frontend/layout/customer_account.xml
@@ -3,16 +3,10 @@
 <body>
     <referenceBlock name="customer_account_navigation">
         <!-- Add menu to the end of the sidebar -->
-        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
+        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-tracking">
             <arguments>
-                <argument name="path" xsi:type="string">bobgo/yourfirstlink/index</argument>
-                <argument name="label" xsi:type="string">Your First Link</argument>
-            </arguments>
-        </block>
-        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
-            <arguments>
-                <argument name="path" xsi:type="string">bobgo/yoursecondlink/index</argument>
-                <argument name="label" xsi:type="string">Your Second Link</argument>
+                <argument name="path" xsi:type="string">bobgo/tracking/index</argument>
+                <argument name="label" xsi:type="string">Tracking</argument>
             </arguments>
         </block>
     </referenceBlock>
diff --git a/view/frontend/templates/secondlink/index.phtml b/view/frontend/templates/secondlink/index.phtml
deleted file mode 100644
index c19dc87..0000000
--- a/view/frontend/templates/secondlink/index.phtml
+++ /dev/null
@@ -1 +0,0 @@
-echo 'My Second Link Page';
diff --git a/view/frontend/templates/yourfirstlink/index.phtml b/view/frontend/templates/tracking/index.phtml
similarity index 100%
rename from view/frontend/templates/yourfirstlink/index.phtml
rename to view/frontend/templates/tracking/index.phtml
-- 
GitLab


From d5dc33c1f7ef981b99e6af4194d2aae146f4e671 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 2 Sep 2024 14:50:18 +0200
Subject: [PATCH 13/56] progress

---
 Block/System/Config/Form/Field/Version.php   |  66 +++++++++
 Block/TrackingBlock.php                      |  23 +++-
 Controller/Tracking/Index.php                | 138 ++++++++++++++++---
 Model/Carrier/UData.php                      |   4 +-
 etc/frontend/di.xml                          |   5 +
 view/frontend/layout/customer_account.xml    |   2 +-
 view/frontend/templates/tracking/index.phtml |  79 ++++++++++-
 view/frontend/web/images/logo.png            | Bin 0 -> 59227 bytes
 8 files changed, 286 insertions(+), 31 deletions(-)
 create mode 100644 Block/System/Config/Form/Field/Version.php
 create mode 100644 view/frontend/web/images/logo.png

diff --git a/Block/System/Config/Form/Field/Version.php b/Block/System/Config/Form/Field/Version.php
new file mode 100644
index 0000000..2ebcbba
--- /dev/null
+++ b/Block/System/Config/Form/Field/Version.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace BobGroup\BobGo\Block\System\Config\Form\Field;
+
+use Magento\Framework\Data\Form\Element\AbstractElement;
+use BobGroup\BobGo\Helper\Data;
+
+/**
+ * Displays Version number in System Configuration
+ *
+ * This block is responsible for displaying the version number of the BobGo extension
+ * in the system configuration settings.
+ *
+ * @website https://www.bobgo.co.za
+ */
+class Version extends \Magento\Config\Block\System\Config\Form\Field
+{
+    /**
+     * @var string
+     */
+    public const EXTENSION_URL = 'https://www.bobgo.co.za';
+
+    /**
+     * @var Data
+     */
+    protected Data $_helper;
+
+    /**
+     * Constructor
+     *
+     * @param \Magento\Backend\Block\Template\Context $context
+     * @param Data $helper
+     */
+    public function __construct(
+        \Magento\Backend\Block\Template\Context $context,
+        Data $helper
+    ) {
+        $this->_helper = $helper;
+        parent::__construct($context);
+    }
+
+    /**
+     * Get HTML for the element
+     *
+     * @param AbstractElement $element
+     * @return string
+     */
+    protected function _getElementHtml(AbstractElement $element): string
+    {
+        $extensionVersion = $this->_helper->getExtensionVersion();
+        $extensionTitle = 'BobGo';
+        $versionLabel = sprintf(
+            '<a href="%s" title="%s" target="_blank">%s</a>',
+            self::EXTENSION_URL,
+            $extensionTitle,
+            $extensionVersion
+        );
+
+        // Set the value using setData
+        $element->setData('value', $versionLabel);
+
+        // Ensure the return value is a string or provide a fallback
+        $value = $element->getData('value');
+        return is_string($value) ? $value : '';
+    }
+}
diff --git a/Block/TrackingBlock.php b/Block/TrackingBlock.php
index f77dab0..69068a2 100644
--- a/Block/TrackingBlock.php
+++ b/Block/TrackingBlock.php
@@ -1,18 +1,27 @@
 <?php
+
 namespace BobGroup\BobGo\Block;
+
+use Magento\Framework\View\Element\Template;
+
 class TrackingBlock extends \Magento\Framework\View\Element\Template
 {
-    public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        array $data = []
-    )
+    protected $response;
+
+    protected function _toHtml()
     {
-        parent::__construct($context, $data);
+        $this->_logger->info('Block HTML rendered: ' . $this->getNameInLayout());
+        return parent::_toHtml();
     }
 
-    public function getHelloWorld()
+    public function setResponse(array $response): self
     {
-        return 'Hello World';
+        $this->_response = $response;
+        return $this;
     }
 
+    public function getResponse()
+    {
+        return $this->response;
+    }
 }
diff --git a/Controller/Tracking/Index.php b/Controller/Tracking/Index.php
index 9955e8d..7d073ba 100644
--- a/Controller/Tracking/Index.php
+++ b/Controller/Tracking/Index.php
@@ -2,38 +2,142 @@
 namespace BobGroup\BobGo\Controller\Tracking;
 
 use Psr\Log\LoggerInterface;
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\View\Result\PageFactory;
+use BobGroup\BobGo\Model\Carrier\UData;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\HTTP\Client\Curl;
+use Magento\Store\Model\StoreManagerInterface;
 
 class Index extends \Magento\Framework\App\Action\Action
 {
-    /**
-     * @var \Magento\Framework\View\Result\PageFactory
-     */
     protected $resultPageFactory;
-
+    protected $jsonFactory;
+    protected $curl;
     protected $logger;
+    protected StoreManagerInterface $storeManager;
 
-    /**
-     * @param \Magento\Framework\App\Action\Context $context
-     * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
-     */
     public function __construct(
-        \Magento\Framework\App\Action\Context $context,
+        Context $context,
+        PageFactory $resultPageFactory,
+        JsonFactory $jsonFactory,
         LoggerInterface $logger,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory
-    )
-    {
+        StoreManagerInterface $storeManager,
+        Curl $curl
+    ) {
         $this->resultPageFactory = $resultPageFactory;
+        $this->jsonFactory = $jsonFactory;
         $this->logger = $logger;
+        $this->storeManager = $storeManager;
+        $this->curl = $curl;
         parent::__construct($context);
     }
-    /**
-     * Default customer account page
-     *
-     * @return void
-     */
+
     public function execute()
     {
         $this->logger->info('Page Controller is executed.');
+        $trackingReference = $this->getRequest()->getParam('order_reference');
+
+        $this->logger->info('Tracking reference:', [$trackingReference]);
+
+        $channel = $this->getStoreUrl();
+
+        $this->logger->info('Channel:', [$channel]);
+
+//        if ($trackingReference) {
+//            $trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
+//
+//            try {
+//                // Make the API call
+//                $this->curl->get($trackingUrl);
+//                $response = $this->curl->getBody();
+//
+//                // Optionally, you can decode the response if it's JSON
+//                $response = json_decode($response, true);
+//
+//                // Handle the response (e.g., display it on the page)
+//                $resultJson = $this->jsonFactory->create();
+//                return $resultJson->setData($response);
+//
+//            } catch (\Exception $e) {
+//                $this->messageManager->addErrorMessage(__('Unable to track the order.'));
+//            }
+//        }
+
+        if ($trackingReference) {
+            $trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
+
+            try {
+                // Make the API call
+                $this->curl->get($trackingUrl);
+                $response = $this->curl->getBody();
+
+                // Decode the response
+                $this->logger->info('Response:', [$response]);
+
+                $decodedResponse = json_decode($response, true);
+                $this->logger->info('Decoded Response:', [$decodedResponse]);
+
+                if (is_array($decodedResponse) && isset($decodedResponse[0])) {
+                    $shipmentData = $decodedResponse[0];
+
+                    // Set response in the block
+                    // In your controller action or block:
+                    $layout = $this->_view->getLayout();
+                    $this->logger->info('Layout Handles: ' . implode(', ', $layout->getUpdate()->getHandles()));
+
+
+                    $blocks = $layout->getAllBlocks();
+
+                    $blockNames = [];
+                    foreach ($blocks as $block) {
+                        $blockNames[] = $block->getNameInLayout();
+                    }
+
+                    $this->logger->info('Available Blocks:', $blockNames);
+
+                    $block = $layout->getBlock('bobgo.tracking.index');
+
+                    $this->logger->info('BobGo block:', [$block]);
+
+                    if ($block) {
+                        $block->setResponse($shipmentData);
+                        $this->logger->info('Block found and data set.');
+                    } else {
+                        $this->logger->info('Block not found.');
+                    }
+                } else {
+                    $this->logger->info('Unexpected response format.');
+                }
+
+            } catch (\Exception $e) {
+                $this->logger->info('Track error: ' . $e->getMessage());
+                $this->messageManager->addErrorMessage(__('Unable to track the order.'));
+            }
+        }
+
         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;
+    }
 }
diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index 47b5d8b..d173baa 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -12,12 +12,12 @@ class UData
      *
      * @var string
      */
-    public const TRACKING = 'https://api.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
+    public const TRACKING = 'https://api.dev.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
 
     /**
      * Rates API Endpoint
      *
      * @var string
      */
-    public const RATES_ENDPOINT = 'https://api.bobgo.co.za/rates-at-checkout/magento';
+    public const RATES_ENDPOINT = 'https://api.dev.bobgo.co.za/rates-at-checkout/magento';
 }
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
index bc1aaeb..3814d81 100644
--- a/etc/frontend/di.xml
+++ b/etc/frontend/di.xml
@@ -13,4 +13,9 @@
             <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\View\Layout">
+        <arguments>
+            <argument name="debug" xsi:type="boolean">true</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/view/frontend/layout/customer_account.xml b/view/frontend/layout/customer_account.xml
index 54c3c21..be9a72f 100644
--- a/view/frontend/layout/customer_account.xml
+++ b/view/frontend/layout/customer_account.xml
@@ -6,7 +6,7 @@
         <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-tracking">
             <arguments>
                 <argument name="path" xsi:type="string">bobgo/tracking/index</argument>
-                <argument name="label" xsi:type="string">Tracking</argument>
+                <argument name="label" xsi:type="string">Track my order</argument>
             </arguments>
         </block>
     </referenceBlock>
diff --git a/view/frontend/templates/tracking/index.phtml b/view/frontend/templates/tracking/index.phtml
index 8c81e6b..f6b8ef8 100644
--- a/view/frontend/templates/tracking/index.phtml
+++ b/view/frontend/templates/tracking/index.phtml
@@ -1,5 +1,76 @@
-<h2>
-    <?php echo $block->getHelloWorld(); ?>
-</h2>
+<style>
+    .track-order-container {
+        max-width: 600px;
+        margin: auto;
+        padding: 20px;
+        border: 1px solid #ddd;
+        background-color: #f9f9f9;
+    }
 
-echo 'My First Link Page';
+    .tracking-details h2 {
+        margin-top: 20px;
+    }
+
+    .tracking-details p {
+        margin: 5px 0;
+    }
+
+    footer {
+        margin-top: 20px;
+        font-size: 0.9em;
+        text-align: center;
+    }
+
+    footer img {
+        display: block;
+        margin: 10px auto;
+    }
+</style>
+
+<div class="track-order-container">
+    <form action="<?php echo $this->getUrl('bobgo/tracking/index'); ?>" method="post">
+        <div class="field">
+            <label for="order_reference"><?php echo __('Order Number/Tracking Reference:'); ?></label>
+            <input type="text" id="order_reference" name="order_reference" required>
+        </div>
+        <br>
+        <div class="actions-toolbar">
+            <button type="submit" class="action submit primary"><?php echo __('Track Order'); ?></button>
+        </div>
+    </form>
+
+<!--    --><?php //if ($response = $block->getResponse()): ?>
+<!--        <div class="tracking-response">-->
+<!--            <!-- Handle and display the API response -->-->
+<!--            <h2>--><?php //echo __('Tracking Information'); ?><!--</h2>-->
+<!--            <p>--><?php //echo __('Status: ' . $response['status']); ?><!--</p>-->
+<!--            <!-- Add more fields as needed from the response -->-->
+<!--        </div>-->
+<!--    --><?php //endif; ?>
+
+        <?php
+
+//<!--    --><?php
+//    $shipmentData = $block->getResponse();
+//    if ($shipmentData && is_array($shipmentData)) {
+//        foreach ($shipmentData as $shipment) {
+//            echo '<div class="tracking-details">';
+//            echo '<h2>' . __('Shipping Details') . '</h2>';
+//            echo '<p>' . __('Shipment: ') . $shipment['shipment_tracking_reference'] . '</p>';
+//            echo '<p>' . __('Order: ') . ltrim($shipment['order_number'], '0') . '</p>';
+//            echo '<p>' . __('Courier: ') . $shipment['courier_name'] . '</p>';
+//
+//            echo '<h2>' . __('Tracking Details') . '</h2>';
+//            echo '<p>' . __('Current Status: ') . $shipment['status_friendly'] . '</p>';
+//
+//            echo '<footer>';
+//            echo '<p>' . __('For additional information, please contact BobGo (support@bobgo.co.za).') . '</p>';
+//            echo '<img src="' . $shipment['courier_logo'] . '" alt="Courier Logo" style="width: 100px;"/>';
+//            echo '</footer>';
+//            echo '</div>';
+//        }
+//    } else {
+//        echo '<p>No tracking data available.</p>';
+//    }
+//    ?>
+</div>
diff --git a/view/frontend/web/images/logo.png b/view/frontend/web/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1214967803c946558511b30e91ac9600543a707
GIT binary patch
literal 59227
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
I>zopr053k>ZvX%Q

literal 0
HcmV?d00001

-- 
GitLab


From abe3e0ebbb8624d4078d9fd9bdb2f9a6c165627a Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 3 Sep 2024 08:37:48 +0200
Subject: [PATCH 14/56] tracking payload data being displayed

---
 Block/TrackingBlock.php                      | 23 +++---
 Controller/Tracking/Index.php                | 59 +++-------------
 view/frontend/templates/tracking/index.phtml | 74 +++++++++++---------
 3 files changed, 61 insertions(+), 95 deletions(-)

diff --git a/Block/TrackingBlock.php b/Block/TrackingBlock.php
index 69068a2..647cb3d 100644
--- a/Block/TrackingBlock.php
+++ b/Block/TrackingBlock.php
@@ -3,25 +3,24 @@
 namespace BobGroup\BobGo\Block;
 
 use Magento\Framework\View\Element\Template;
+use Magento\Framework\Registry;
 
 class TrackingBlock extends \Magento\Framework\View\Element\Template
 {
-    protected $response;
+    protected $registry;
 
-    protected function _toHtml()
-    {
-        $this->_logger->info('Block HTML rendered: ' . $this->getNameInLayout());
-        return parent::_toHtml();
-    }
-
-    public function setResponse(array $response): self
-    {
-        $this->_response = $response;
-        return $this;
+    public function __construct(
+        Template\Context $context,
+        Registry $registry,
+        array $data = []
+    ) {
+        $this->registry = $registry;
+        parent::__construct($context, $data);
     }
 
     public function getResponse()
     {
-        return $this->response;
+        return $this->registry->registry('shipment_data');
     }
 }
+
diff --git a/Controller/Tracking/Index.php b/Controller/Tracking/Index.php
index 7d073ba..0fc445b 100644
--- a/Controller/Tracking/Index.php
+++ b/Controller/Tracking/Index.php
@@ -1,13 +1,14 @@
 <?php
 namespace BobGroup\BobGo\Controller\Tracking;
 
-use Psr\Log\LoggerInterface;
 use Magento\Framework\App\Action\Context;
 use Magento\Framework\View\Result\PageFactory;
-use BobGroup\BobGo\Model\Carrier\UData;
+use Magento\Framework\Registry;
+use Psr\Log\LoggerInterface;
 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
 {
@@ -15,6 +16,7 @@ class Index extends \Magento\Framework\App\Action\Action
     protected $jsonFactory;
     protected $curl;
     protected $logger;
+    protected $registry;
     protected StoreManagerInterface $storeManager;
 
     public function __construct(
@@ -23,13 +25,15 @@ class Index extends \Magento\Framework\App\Action\Action
         JsonFactory $jsonFactory,
         LoggerInterface $logger,
         StoreManagerInterface $storeManager,
-        Curl $curl
+        Curl $curl,
+        Registry $registry // Add Registry
     ) {
         $this->resultPageFactory = $resultPageFactory;
         $this->jsonFactory = $jsonFactory;
         $this->logger = $logger;
         $this->storeManager = $storeManager;
         $this->curl = $curl;
+        $this->registry = $registry; // Assign Registry
         parent::__construct($context);
     }
 
@@ -44,35 +48,13 @@ class Index extends \Magento\Framework\App\Action\Action
 
         $this->logger->info('Channel:', [$channel]);
 
-//        if ($trackingReference) {
-//            $trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
-//
-//            try {
-//                // Make the API call
-//                $this->curl->get($trackingUrl);
-//                $response = $this->curl->getBody();
-//
-//                // Optionally, you can decode the response if it's JSON
-//                $response = json_decode($response, true);
-//
-//                // Handle the response (e.g., display it on the page)
-//                $resultJson = $this->jsonFactory->create();
-//                return $resultJson->setData($response);
-//
-//            } catch (\Exception $e) {
-//                $this->messageManager->addErrorMessage(__('Unable to track the order.'));
-//            }
-//        }
-
         if ($trackingReference) {
             $trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
 
             try {
-                // Make the API call
                 $this->curl->get($trackingUrl);
                 $response = $this->curl->getBody();
 
-                // Decode the response
                 $this->logger->info('Response:', [$response]);
 
                 $decodedResponse = json_decode($response, true);
@@ -81,31 +63,10 @@ class Index extends \Magento\Framework\App\Action\Action
                 if (is_array($decodedResponse) && isset($decodedResponse[0])) {
                     $shipmentData = $decodedResponse[0];
 
-                    // Set response in the block
-                    // In your controller action or block:
-                    $layout = $this->_view->getLayout();
-                    $this->logger->info('Layout Handles: ' . implode(', ', $layout->getUpdate()->getHandles()));
-
-
-                    $blocks = $layout->getAllBlocks();
-
-                    $blockNames = [];
-                    foreach ($blocks as $block) {
-                        $blockNames[] = $block->getNameInLayout();
-                    }
-
-                    $this->logger->info('Available Blocks:', $blockNames);
-
-                    $block = $layout->getBlock('bobgo.tracking.index');
-
-                    $this->logger->info('BobGo block:', [$block]);
+                    // Save data to the registry
+                    $this->registry->register('shipment_data', $shipmentData);
+                    $this->logger->info('Shipment data registered in the registry.');
 
-                    if ($block) {
-                        $block->setResponse($shipmentData);
-                        $this->logger->info('Block found and data set.');
-                    } else {
-                        $this->logger->info('Block not found.');
-                    }
                 } else {
                     $this->logger->info('Unexpected response format.');
                 }
diff --git a/view/frontend/templates/tracking/index.phtml b/view/frontend/templates/tracking/index.phtml
index f6b8ef8..f6e2b23 100644
--- a/view/frontend/templates/tracking/index.phtml
+++ b/view/frontend/templates/tracking/index.phtml
@@ -39,38 +39,44 @@
         </div>
     </form>
 
-<!--    --><?php //if ($response = $block->getResponse()): ?>
-<!--        <div class="tracking-response">-->
-<!--            <!-- Handle and display the API response -->-->
-<!--            <h2>--><?php //echo __('Tracking Information'); ?><!--</h2>-->
-<!--            <p>--><?php //echo __('Status: ' . $response['status']); ?><!--</p>-->
-<!--            <!-- Add more fields as needed from the response -->-->
-<!--        </div>-->
-<!--    --><?php //endif; ?>
-
-        <?php
-
-//<!--    --><?php
-//    $shipmentData = $block->getResponse();
-//    if ($shipmentData && is_array($shipmentData)) {
-//        foreach ($shipmentData as $shipment) {
-//            echo '<div class="tracking-details">';
-//            echo '<h2>' . __('Shipping Details') . '</h2>';
-//            echo '<p>' . __('Shipment: ') . $shipment['shipment_tracking_reference'] . '</p>';
-//            echo '<p>' . __('Order: ') . ltrim($shipment['order_number'], '0') . '</p>';
-//            echo '<p>' . __('Courier: ') . $shipment['courier_name'] . '</p>';
-//
-//            echo '<h2>' . __('Tracking Details') . '</h2>';
-//            echo '<p>' . __('Current Status: ') . $shipment['status_friendly'] . '</p>';
-//
-//            echo '<footer>';
-//            echo '<p>' . __('For additional information, please contact BobGo (support@bobgo.co.za).') . '</p>';
-//            echo '<img src="' . $shipment['courier_logo'] . '" alt="Courier Logo" style="width: 100px;"/>';
-//            echo '</footer>';
-//            echo '</div>';
-//        }
-//    } else {
-//        echo '<p>No tracking data available.</p>';
-//    }
-//    ?>
+    <?php
+    $shipmentData = $this->getResponse();
+
+    if ($shipmentData && is_array($shipmentData)) {
+        echo '<div class="tracking-details">';
+        echo '<h2>' . __('Shipping Details') . '</h2>';
+
+        // Ensure each accessed array key exists and contains an array where expected
+        if (isset($shipmentData['shipment_tracking_reference'])) {
+            echo '<p>' . __('Shipment: ') . $shipmentData['shipment_tracking_reference'] . '</p>';
+        }
+
+        if (isset($shipmentData['order_number'])) {
+            echo '<p>' . __('Order: ') . ltrim($shipmentData['order_number'], '0') . '</p>';
+        }
+
+        if (isset($shipmentData['courier_name'])) {
+            echo '<p>' . __('Courier: ') . $shipmentData['courier_name'] . '</p>';
+        }
+
+        echo '<h2>' . __('Tracking Details') . '</h2>';
+
+        if (isset($shipmentData['status_friendly'])) {
+            echo '<p>' . __('Current Status: ') . $shipmentData['status_friendly'] . '</p>';
+        }
+
+        if (isset($shipmentData['courier_logo'])) {
+            echo '<footer>';
+            echo '<p>' . __('For additional information, please contact BobGo (support@bobgo.co.za).') . '</p>';
+            echo '<img src="' . $shipmentData['courier_logo'] . '" alt="Courier Logo" style="width: 100px;"/>';
+            echo '</footer>';
+        }
+
+        echo '</div>';
+    } else {
+        echo '<p>No tracking data available.</p>';
+    }
+    ?>
+
+
 </div>
-- 
GitLab


From 62c32bf0fcec9de4fa66e7cdc0dcbf287baf55dc Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 3 Sep 2024 10:41:00 +0200
Subject: [PATCH 15/56] link the setting to the tracking page

---
 Block/TrackOrderLink.php                      |  39 +++++
 Controller/Tracking/Index.php                 |  19 +++
 view/frontend/layout/bobgo_tracking_index.xml |   2 +-
 view/frontend/layout/customer_account.xml     |  22 +--
 view/frontend/templates/tracking/index.phtml  | 143 ++++++++++++------
 view/frontend/web/images/logo.png             | Bin 59227 -> 0 bytes
 6 files changed, 164 insertions(+), 61 deletions(-)
 create mode 100644 Block/TrackOrderLink.php
 delete mode 100644 view/frontend/web/images/logo.png

diff --git a/Block/TrackOrderLink.php b/Block/TrackOrderLink.php
new file mode 100644
index 0000000..54c3c6f
--- /dev/null
+++ b/Block/TrackOrderLink.php
@@ -0,0 +1,39 @@
+<?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, // Add this dependency
+        array $data = []
+    ) {
+        $this->scopeConfig = $scopeConfig;
+        parent::__construct($context, $defaultPath, $data); // Pass it to the parent constructor
+    }
+
+    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
+        );
+
+        if (!$isEnabled) {
+            return ''; // Return an empty string if the feature is disabled
+        }
+
+        return parent::_toHtml(); // Use the parent class's rendering method
+    }
+}
+
+
+
diff --git a/Controller/Tracking/Index.php b/Controller/Tracking/Index.php
index 0fc445b..c3a01ee 100644
--- a/Controller/Tracking/Index.php
+++ b/Controller/Tracking/Index.php
@@ -5,6 +5,8 @@ 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;
@@ -16,6 +18,8 @@ class Index extends \Magento\Framework\App\Action\Action
     protected $jsonFactory;
     protected $curl;
     protected $logger;
+    protected $scopeConfig;
+    protected $redirectFactory;
     protected $registry;
     protected StoreManagerInterface $storeManager;
 
@@ -24,6 +28,8 @@ class Index extends \Magento\Framework\App\Action\Action
         PageFactory $resultPageFactory,
         JsonFactory $jsonFactory,
         LoggerInterface $logger,
+        ScopeConfigInterface $scopeConfig,
+        RedirectFactory $redirectFactory,
         StoreManagerInterface $storeManager,
         Curl $curl,
         Registry $registry // Add Registry
@@ -31,6 +37,8 @@ class Index extends \Magento\Framework\App\Action\Action
         $this->resultPageFactory = $resultPageFactory;
         $this->jsonFactory = $jsonFactory;
         $this->logger = $logger;
+        $this->scopeConfig = $scopeConfig;
+        $this->redirectFactory = $redirectFactory;
         $this->storeManager = $storeManager;
         $this->curl = $curl;
         $this->registry = $registry; // Assign Registry
@@ -39,6 +47,17 @@ class Index extends \Magento\Framework\App\Action\Action
 
     public function execute()
     {
+        // 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');
+        }
+
         $this->logger->info('Page Controller is executed.');
         $trackingReference = $this->getRequest()->getParam('order_reference');
 
diff --git a/view/frontend/layout/bobgo_tracking_index.xml b/view/frontend/layout/bobgo_tracking_index.xml
index 6e842d7..e36faa5 100644
--- a/view/frontend/layout/bobgo_tracking_index.xml
+++ b/view/frontend/layout/bobgo_tracking_index.xml
@@ -3,7 +3,7 @@
     <update handle="customer_account"/>
     <head>
         <title>
-            Tracking
+            Track my order
         </title>
     </head>
     <body>
diff --git a/view/frontend/layout/customer_account.xml b/view/frontend/layout/customer_account.xml
index be9a72f..701335d 100644
--- a/view/frontend/layout/customer_account.xml
+++ b/view/frontend/layout/customer_account.xml
@@ -1,14 +1,14 @@
 <?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="customer_account_navigation">
-        <!-- Add menu to the end of the sidebar -->
-        <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-tracking">
-            <arguments>
-                <argument name="path" xsi:type="string">bobgo/tracking/index</argument>
-                <argument name="label" xsi:type="string">Track my order</argument>
-            </arguments>
-        </block>
-    </referenceBlock>
-</body>
+    <body>
+        <referenceBlock name="customer_account_navigation">
+            <!-- Add conditional menu to the end of the sidebar -->
+            <block class="BobGroup\BobGo\Block\TrackOrderLink" name="customer-account-navigation-tracking">
+                <arguments>
+                    <argument name="path" xsi:type="string">bobgo/tracking/index</argument>
+                    <argument name="label" xsi:type="string">Track my order</argument>
+                </arguments>
+            </block>
+        </referenceBlock>
+    </body>
 </page>
diff --git a/view/frontend/templates/tracking/index.phtml b/view/frontend/templates/tracking/index.phtml
index f6e2b23..b9f8ba0 100644
--- a/view/frontend/templates/tracking/index.phtml
+++ b/view/frontend/templates/tracking/index.phtml
@@ -1,3 +1,7 @@
+<?php
+$shipmentData = $this->getResponse();
+?>
+
 <style>
     .track-order-container {
         max-width: 600px;
@@ -28,55 +32,96 @@
 </style>
 
 <div class="track-order-container">
-    <form action="<?php echo $this->getUrl('bobgo/tracking/index'); ?>" method="post">
-        <div class="field">
-            <label for="order_reference"><?php echo __('Order Number/Tracking Reference:'); ?></label>
-            <input type="text" id="order_reference" name="order_reference" required>
-        </div>
-        <br>
-        <div class="actions-toolbar">
-            <button type="submit" class="action submit primary"><?php echo __('Track Order'); ?></button>
+    <?php if (empty($shipmentData)) : ?>
+        <form action="<?php echo $this->getUrl('bobgo/tracking/index'); ?>" method="post" class="track-order-form">
+            <div class="field">
+                <label for="order_reference"><?php echo __('Order Number/Tracking Reference:'); ?></label>
+                <input type="text" id="order_reference" name="order_reference" required>
+            </div>
+            <br>
+            <div class="actions-toolbar">
+                <button type="submit" class="action submit primary"><?php echo __('Track Order'); ?></button>
+            </div>
+        </form>
+    <?php endif; ?>
+
+    <?php if ($shipmentData && is_array($shipmentData)) : ?>
+        <div class="tracking-details">
+            <h2><?php echo __('Shipping Details'); ?></h2>
+
+            <?php if (isset($shipmentData['shipment_tracking_reference'])) : ?>
+                <p><strong><?php echo __('Shipment:'); ?></strong> <?php echo $shipmentData['shipment_tracking_reference']; ?></p>
+            <?php endif; ?>
+
+            <?php if (isset($shipmentData['order_number'])) : ?>
+                <p><strong><?php echo __('Order:'); ?></strong> <?php echo ltrim($shipmentData['order_number'], '0'); ?></p>
+            <?php endif; ?>
+
+            <?php if (isset($shipmentData['courier_name'])) : ?>
+                <p><strong><?php echo __('Courier:'); ?></strong> <?php echo $shipmentData['courier_name']; ?></p>
+            <?php endif; ?>
+
+            <br>
+            <h2><?php echo __('Tracking Details'); ?></h2>
+
+            <?php if (isset($shipmentData['status']) && isset($shipmentData['status_friendly'])) : ?>
+                <?php if ($shipmentData['status'] == 'pending-collection') : ?>
+                    <p><?php echo 'Your shipment will be collected soon. Please check back later for more information.' ?></p>
+                    <p><strong><?php echo __('Current Status:'); ?></strong> <?php echo $shipmentData['status_friendly']; ?></p>
+                <?php elseif (in_array($shipmentData['status'], ['cancelled-by-courier', 'cancelled'])) : ?>
+                    <p><?php echo 'The shipment has been cancelled.'; ?></p>
+                    <p><strong><?php echo __('Current Status:'); ?></strong> <?php echo $shipmentData['status_friendly']; ?></p>
+                <?php else : ?>
+                    <?php if (empty($shipmentData['checkpoints'])) : ?>
+                        <p><?php echo 'Tracking information is not yet available. Please check back later for more information.'; ?></p>
+                    <?php else : ?>
+                        <p><?php echo 'Tracking information is available below:'; ?></p>
+                        <table id="table_checkpoints">
+                            <thead>
+                            <tr>
+                                <th><?php echo __('Date and Time'); ?></th>
+                                <th><?php echo __('Status'); ?></th>
+                                <th><?php echo __('Message'); ?></th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <?php foreach ($shipmentData['checkpoints'] as $checkpoint) : ?>
+                                <tr>
+                                    <td>
+                                        <?php
+                                        $timeDate = new DateTime($checkpoint['time']);
+                                        echo $timeDate->format('Y M d, H:i');
+                                        ?>
+                                    </td>
+                                    <td><strong><?php echo $checkpoint['status_friendly']; ?></strong></td>
+                                    <td><?php echo $checkpoint['message']; ?></td>
+                                </tr>
+                            <?php endforeach; ?>
+                            </tbody>
+                        </table>
+                    <?php endif; ?>
+                <?php endif; ?>
+            <?php endif; ?>
         </div>
-    </form>
-
-    <?php
-    $shipmentData = $this->getResponse();
-
-    if ($shipmentData && is_array($shipmentData)) {
-        echo '<div class="tracking-details">';
-        echo '<h2>' . __('Shipping Details') . '</h2>';
-
-        // Ensure each accessed array key exists and contains an array where expected
-        if (isset($shipmentData['shipment_tracking_reference'])) {
-            echo '<p>' . __('Shipment: ') . $shipmentData['shipment_tracking_reference'] . '</p>';
-        }
-
-        if (isset($shipmentData['order_number'])) {
-            echo '<p>' . __('Order: ') . ltrim($shipmentData['order_number'], '0') . '</p>';
-        }
-
-        if (isset($shipmentData['courier_name'])) {
-            echo '<p>' . __('Courier: ') . $shipmentData['courier_name'] . '</p>';
-        }
-
-        echo '<h2>' . __('Tracking Details') . '</h2>';
-
-        if (isset($shipmentData['status_friendly'])) {
-            echo '<p>' . __('Current Status: ') . $shipmentData['status_friendly'] . '</p>';
-        }
-
-        if (isset($shipmentData['courier_logo'])) {
-            echo '<footer>';
-            echo '<p>' . __('For additional information, please contact BobGo (support@bobgo.co.za).') . '</p>';
-            echo '<img src="' . $shipmentData['courier_logo'] . '" alt="Courier Logo" style="width: 100px;"/>';
-            echo '</footer>';
-        }
-
-        echo '</div>';
-    } else {
-        echo '<p>No tracking data available.</p>';
-    }
-    ?>
-
 
+    <br>
+        <footer>
+            <p>
+                <?php
+                echo sprintf(
+                    __('For additional information, please contact %s (%s) and quote tracking reference %s.'),
+                    $shipmentData['courier_name'],
+                    $shipmentData['courier_phone'],
+                    $shipmentData['id']
+                );
+                ?>
+            </p>
+            <img id="show_branding" class="image"
+                 src="https://img.bob.co.za/bobgo/image/upload/bobgo-logos/bobgo_logo_smart_shipping_black.png?tr=w-400&ts=20231024"
+                 alt="Bob Go logo"  style="width: 200px;">
+        </footer>
+    <?php else : ?>
+    <br>
+        <p><?php echo __('No tracking data available.'); ?></p>
+    <?php endif; ?>
 </div>
diff --git a/view/frontend/web/images/logo.png b/view/frontend/web/images/logo.png
deleted file mode 100644
index a1214967803c946558511b30e91ac9600543a707..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 59227
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
I>zopr053k>ZvX%Q

-- 
GitLab


From 436e55f7ca00c39368da000e4f637d1796e349b2 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 3 Sep 2024 11:16:38 +0200
Subject: [PATCH 16/56] cleanup

---
 Block/TrackOrderLink.php      | 10 ++++++----
 Controller/Tracking/Index.php | 25 +++++--------------------
 etc/frontend/di.xml           |  5 -----
 3 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/Block/TrackOrderLink.php b/Block/TrackOrderLink.php
index 54c3c6f..ada8c22 100644
--- a/Block/TrackOrderLink.php
+++ b/Block/TrackOrderLink.php
@@ -12,11 +12,11 @@ class TrackOrderLink extends Current
     public function __construct(
         \Magento\Framework\View\Element\Template\Context $context,
         ScopeConfigInterface $scopeConfig,
-        \Magento\Framework\App\DefaultPathInterface $defaultPath, // Add this dependency
+        \Magento\Framework\App\DefaultPathInterface $defaultPath,
         array $data = []
     ) {
         $this->scopeConfig = $scopeConfig;
-        parent::__construct($context, $defaultPath, $data); // Pass it to the parent constructor
+        parent::__construct($context, $defaultPath, $data);
     }
 
     protected function _toHtml()
@@ -27,11 +27,13 @@ class TrackOrderLink extends Current
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE
         );
 
+        // Return an empty string if the feature is disabled
         if (!$isEnabled) {
-            return ''; // Return an empty string if the feature is disabled
+            return '';
         }
 
-        return parent::_toHtml(); // Use the parent class's rendering method
+        // Use the parent class's rendering method
+        return parent::_toHtml();
     }
 }
 
diff --git a/Controller/Tracking/Index.php b/Controller/Tracking/Index.php
index c3a01ee..78e527f 100644
--- a/Controller/Tracking/Index.php
+++ b/Controller/Tracking/Index.php
@@ -32,7 +32,7 @@ class Index extends \Magento\Framework\App\Action\Action
         RedirectFactory $redirectFactory,
         StoreManagerInterface $storeManager,
         Curl $curl,
-        Registry $registry // Add Registry
+        Registry $registry
     ) {
         $this->resultPageFactory = $resultPageFactory;
         $this->jsonFactory = $jsonFactory;
@@ -41,12 +41,13 @@ class Index extends \Magento\Framework\App\Action\Action
         $this->redirectFactory = $redirectFactory;
         $this->storeManager = $storeManager;
         $this->curl = $curl;
-        $this->registry = $registry; // Assign Registry
+        $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',
@@ -58,48 +59,32 @@ class Index extends \Magento\Framework\App\Action\Action
             return $this->redirectFactory->create()->setPath('noroute');
         }
 
-        $this->logger->info('Page Controller is executed.');
         $trackingReference = $this->getRequest()->getParam('order_reference');
 
-        $this->logger->info('Tracking reference:', [$trackingReference]);
-
         $channel = $this->getStoreUrl();
 
-        $this->logger->info('Channel:', [$channel]);
-
         if ($trackingReference) {
             $trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
-
-            try {
                 $this->curl->get($trackingUrl);
                 $response = $this->curl->getBody();
 
-                $this->logger->info('Response:', [$response]);
-
                 $decodedResponse = json_decode($response, true);
-                $this->logger->info('Decoded Response:', [$decodedResponse]);
 
                 if (is_array($decodedResponse) && isset($decodedResponse[0])) {
                     $shipmentData = $decodedResponse[0];
 
                     // Save data to the registry
                     $this->registry->register('shipment_data', $shipmentData);
-                    $this->logger->info('Shipment data registered in the registry.');
 
                 } else {
-                    $this->logger->info('Unexpected response format.');
+                    // Return early the response is not valid
+                    return $this->resultPageFactory->create();
                 }
-
-            } catch (\Exception $e) {
-                $this->logger->info('Track error: ' . $e->getMessage());
-                $this->messageManager->addErrorMessage(__('Unable to track the order.'));
-            }
         }
 
         return $this->resultPageFactory->create();
     }
 
-
     private function getStoreUrl(): string
     {
         $url = $this->storeManager->getStore()->getBaseUrl();
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
index 3814d81..bc1aaeb 100644
--- a/etc/frontend/di.xml
+++ b/etc/frontend/di.xml
@@ -13,9 +13,4 @@
             <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
         </arguments>
     </type>
-    <type name="Magento\Framework\View\Layout">
-        <arguments>
-            <argument name="debug" xsi:type="boolean">true</argument>
-        </arguments>
-    </type>
 </config>
-- 
GitLab


From 17cd8bd9f2b8197c1088d70feef2f3ab6e264b66 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 3 Sep 2024 12:57:26 +0200
Subject: [PATCH 17/56] remove old tracking classes and functions

---
 Model/Carrier/BobGo.php                       | 269 ------------------
 .../DataProviders/Tracking/ChangeTitle.php    |  31 --
 Plugin/Block/Tracking/PopUpDeliveryDate.php   |  53 ----
 .../Tracking/ChangeTitleTest.php              |  62 ----
 .../Block/Tracking/PopUpDeliveryDateTest.php  |  92 ------
 5 files changed, 507 deletions(-)
 delete mode 100644 Plugin/Block/DataProviders/Tracking/ChangeTitle.php
 delete mode 100644 Plugin/Block/Tracking/PopUpDeliveryDate.php
 delete mode 100644 Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php
 delete mode 100644 Test/Unit/Plugin/Block/Tracking/PopUpDeliveryDateTest.php

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 386e4cb..2809b13 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -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
      *
@@ -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'.
      *
@@ -883,26 +699,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 +772,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 +804,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 +951,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.
      *
diff --git a/Plugin/Block/DataProviders/Tracking/ChangeTitle.php b/Plugin/Block/DataProviders/Tracking/ChangeTitle.php
deleted file mode 100644
index a035d23..0000000
--- a/Plugin/Block/DataProviders/Tracking/ChangeTitle.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?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;
-    }
-}
diff --git a/Plugin/Block/Tracking/PopUpDeliveryDate.php b/Plugin/Block/Tracking/PopUpDeliveryDate.php
deleted file mode 100644
index bb37528..0000000
--- a/Plugin/Block/Tracking/PopUpDeliveryDate.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?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 '';
-    }
-}
diff --git a/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php b/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php
deleted file mode 100644
index 4d8bd9d..0000000
--- a/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?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);
-    }
-}
diff --git a/Test/Unit/Plugin/Block/Tracking/PopUpDeliveryDateTest.php b/Test/Unit/Plugin/Block/Tracking/PopUpDeliveryDateTest.php
deleted file mode 100644
index 6c01770..0000000
--- a/Test/Unit/Plugin/Block/Tracking/PopUpDeliveryDateTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?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);
-    }
-}
-- 
GitLab


From 396e93a12670b55ea5174f2b598e03cb809cae4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 25 Sep 2024 13:07:50 +0200
Subject: [PATCH 18/56] Update the logo

---
 view/frontend/templates/tracking/index.phtml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/frontend/templates/tracking/index.phtml b/view/frontend/templates/tracking/index.phtml
index b9f8ba0..5895f01 100644
--- a/view/frontend/templates/tracking/index.phtml
+++ b/view/frontend/templates/tracking/index.phtml
@@ -117,7 +117,7 @@ $shipmentData = $this->getResponse();
                 ?>
             </p>
             <img id="show_branding" class="image"
-                 src="https://img.bob.co.za/bobgo/image/upload/bobgo-logos/bobgo_logo_smart_shipping_black.png?tr=w-400&ts=20231024"
+                 src="https://ik.imagekit.io/z1viz85yxs/prod-v3/bobgo/corporate-identity/bobgo_logo_smart_shipping.png?tr=w-400"
                  alt="Bob Go logo"  style="width: 200px;">
         </footer>
     <?php else : ?>
-- 
GitLab


From dbcb4eb74924ac5493699a08003d149a6eb14722 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 2 Oct 2024 15:44:00 +0200
Subject: [PATCH 19/56] triggerWebhookTest

---
 Model/Carrier/BobGo.php           | 87 +++++++++++++++++++++++++++++++
 Model/Carrier/UData.php           |  2 +-
 Observer/ConfigChangeObserver.php | 20 +++++++
 Observer/OrderCreateWebhook.php   |  1 +
 Observer/OrderWebhookBase.php     | 24 +++++++--
 etc/adminhtml/system.xml          | 16 ++++++
 6 files changed, 145 insertions(+), 5 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 386e4cb..51cf36b 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -864,6 +864,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.
      *
@@ -1310,4 +1315,86 @@ 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
+        );
+
+        $isEnabled = $this->scopeConfig->getValue(
+            'carriers/bobgo/enable_webhooks',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+        );
+
+        // Convert the string to a boolean value
+        $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
+
+//        if (!$webhookKey) {
+//            $this->_logger->error('Webhook key not configured.');
+//            return false;
+//        }
+
+        $storeId = strval($this->_storeManager->getStore()->getId());
+
+        $payload = [
+            'event' => 'webhook_validation',
+            'channel_identifier' => $this->getBaseUrl(),
+            'store_id' => $storeId,
+            'webhooks_enabled' => $isEnabled,
+        ];
+
+        try {
+            // 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($payload);
+            $this->_logger->info('Webhooks payload: ' . $payloadJson);
+            if ($payloadJson === false) {
+                throw new \RuntimeException('Failed to encode payload to JSON.');
+            }
+
+            $this->curl->addHeader('Content-Type', 'application/json');
+            $this->curl->post($this->getWebhookUrl(), $payloadJson);
+            $statusCode = $this->curl->getStatus();
+            $this->_logger->info('Webhooks statuscode: ' . $statusCode);
+            $responseBody = $this->curl->getBody();
+            $this->_logger->info('Webhooks response: ' . $responseBody);
+
+            $response = json_decode($responseBody, true);
+
+            if ($statusCode == 200 && isset($response['success']) && $response['success'] === true) {
+                $this->_logger->info('Webhook validation successful.');
+//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+                return true;
+            } else {
+                $this->_logger->error('Webhook validation failed: ' . ($response['message'] ?? 'Unknown error'));
+//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+                return false;
+            }
+        } catch (\Exception $e) {
+            $this->_logger->error('Webhook validation exception: ' . $e->getMessage());
+//            throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+            return false;
+        }
+    }
+
 }
diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index adf83a2..a7e5d2e 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
 }
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 1b6c072..528dd82 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -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,24 @@ class ConfigChangeObserver implements ObserverInterface
                 }
             }
         }
+
+        // Test for webhooks
+        if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
+//            if ($this->bobGo->isWebhookEnabled()) {
+                $this->logger->info('Webhooks test start: ');
+                $result = $this->bobGo->triggerWebhookTest();
+                $this->logger->info('Webhooks test end: ' . $result);
+
+                if ($result) {
+                    $this->messageManager->addSuccessMessage(
+                        __('Webhook validation successful.')
+                    );
+                } else {
+                    $this->messageManager->addErrorMessage(
+                        __('Webhook validation failed. Please check the webhook key and try again.')
+                    );
+                }
+//            }
+        }
     }
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 74f1ce4..f605801 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -15,5 +15,6 @@ class OrderCreateWebhook extends OrderWebhookBase
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order);
+        $this->logger->info('Webhooks sent');
     }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index eeb106e..db27d61 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -3,6 +3,7 @@
 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;
@@ -13,18 +14,29 @@ abstract class OrderWebhookBase implements ObserverInterface
     protected Curl $curl;
     protected LoggerInterface $logger;
     protected StoreManagerInterface $storeManager;
+    protected ScopeConfigInterface $scopeConfig;
 
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig)
     {
         $this->logger = $logger;
         $this->curl = $curl;
         $this->storeManager = $storeManager;
+        $this->scopeConfig = $scopeConfig;
     }
 
     protected function sendWebhook($order)
     {
+        $enabled = $this->scopeConfig->getValue('carriers/bobgo/enable_webhooks', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+
+        // Return early if webhooks is disabled
+        if (!$enabled) {
+            $this->logger->info('Webhooks are disabled. Exiting webhook process for order: ' . $order->getIncrementId());
+            return;
+        }
+
         // Webhook URL
         $url = $this->getWebhookUrl();
+        $this->logger->info('Webhooks url: ' . $url);
 
         $storeId = $this->getStoreId();
 
@@ -54,14 +66,17 @@ abstract class OrderWebhookBase implements ObserverInterface
 
         // Send the webhook
         $this->makeHttpPostRequest($url, $data, $storeId);
+        $this->logger->info('Webhooks sent');
     }
 
     private function makeHttpPostRequest($url, $data, $storeId)
     {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the signature using the webhook key saved in config
+        $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+        $this->logger->info('Webhooks - key: ' . $webhookKey);
+//        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
         // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+        $rawSignature = hash_hmac('sha256', $storeId, $webhookKey, true);
 
         // Encode the binary data in Base64
         $signature = base64_encode($rawSignature);
@@ -79,6 +94,7 @@ abstract class OrderWebhookBase implements ObserverInterface
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
+        $this->logger->info('Webhooks payload: ' . $payloadJson);
     }
 
     private function getWebhookUrl(): string
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 410c2c2..3f4b31f 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -28,6 +28,22 @@
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                     <comment>Displays the delivery timeframe and additional service level description, as configured on Bob Go.</comment>
                 </field>
+
+                <!-- Enable Webhooks Checkbox -->
+                <field id="enable_webhooks" translate="label" type="select" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Enable webhooks</label>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                    <comment>Enable or disable the webhook functionality for Bob Go.</comment>
+                </field>
+
+                <!-- Webhook Key Input Field -->
+                <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Webhook key</label>
+                    <comment>Enter the webhook key for authentication.</comment>
+                    <depends>
+                        <field id="enable_webhooks">1</field>
+                    </depends>
+                </field>
             </group>
         </section>
     </system>
-- 
GitLab


From b77abc3818a1ced5d22db839ca743cf8bd32b7d1 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 10:10:05 +0200
Subject: [PATCH 20/56] webhooks test update and webhooks payload

---
 Model/Carrier/BobGo.php           |  4 ---
 Observer/ConfigChangeObserver.php | 14 ++++----
 Observer/OrderCreateWebhook.php   |  1 -
 Observer/OrderWebhookBase.php     | 57 +++++--------------------------
 4 files changed, 17 insertions(+), 59 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 51cf36b..fdb7283 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1343,10 +1343,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         // Convert the string to a boolean value
         $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
 
-//        if (!$webhookKey) {
-//            $this->_logger->error('Webhook key not configured.');
-//            return false;
-//        }
 
         $storeId = strval($this->_storeManager->getStore()->getId());
 
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 528dd82..9cbde5d 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -74,21 +74,23 @@ class ConfigChangeObserver implements ObserverInterface
 
         // Test for webhooks
         if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
-//            if ($this->bobGo->isWebhookEnabled()) {
-                $this->logger->info('Webhooks test start: ');
-                $result = $this->bobGo->triggerWebhookTest();
-                $this->logger->info('Webhooks test end: ' . $result);
+            $this->logger->info('Webhooks test start: ');
+            $result = $this->bobGo->triggerWebhookTest();
+            $this->logger->info('Webhooks test end: ' . $result);
 
+            if ($this->bobGo->isWebhookEnabled()) {
                 if ($result) {
                     $this->messageManager->addSuccessMessage(
                         __('Webhook validation successful.')
                     );
                 } else {
                     $this->messageManager->addErrorMessage(
-                        __('Webhook validation failed. Please check the webhook key and try again.')
+                        __('Webhook validation failed. Please check your internet connection
+                        and get the webhook key for your channel on Bob Go sales channels page.
+                        https://my.bobgo.co.za/sales-channels')
                     );
                 }
-//            }
+            }
         }
     }
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index f605801..74f1ce4 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -15,6 +15,5 @@ class OrderCreateWebhook extends OrderWebhookBase
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order);
-        $this->logger->info('Webhooks sent');
     }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index db27d61..6a5163f 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -8,6 +8,7 @@ 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
 {
@@ -15,66 +16,48 @@ abstract class OrderWebhookBase implements ObserverInterface
     protected LoggerInterface $logger;
     protected StoreManagerInterface $storeManager;
     protected ScopeConfigInterface $scopeConfig;
+    protected $bobGo;
 
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig)
+    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)
     {
-        $enabled = $this->scopeConfig->getValue('carriers/bobgo/enable_webhooks', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-
-        // Return early if webhooks is disabled
-        if (!$enabled) {
-            $this->logger->info('Webhooks are disabled. Exiting webhook process for order: ' . $order->getIncrementId());
+        // Return early if not enabled
+        if (!$this->bobGo->isWebhookEnabled()) {
             return;
         }
 
         // Webhook URL
         $url = $this->getWebhookUrl();
-        $this->logger->info('Webhooks url: ' . $url);
 
         $storeId = $this->getStoreId();
 
         $orderId = $order->getId();
 
-        // Get the order creation time
-        $createdAt = strtotime($order->getCreatedAt());
-        $currentTime = time();
-
-        // Define a time threshold  to consider the order as newly created
-        $threshold = 5; // 5  seconds
-
-        // Determine the event type based on the creation time
-        if (($currentTime - $createdAt) < $threshold) {
-            $eventType = 'order_created';
-        } else {
-            $eventType = 'order_updated';
-        }
-
         // Prepare payload
         $data = [
-            'event' => $eventType,
+            'event' => 'order_updated',
             'order_id' => $orderId,
-            'channel_identifier' => $this->getStoreUrl(),
+            'channel_identifier' => $this->bobGo->getBaseUrl(),
             'store_id' => $storeId,
+            'webhooks_enabled' => true, // If we get to this point webhooks are enabled
         ];
 
         // Send the webhook
         $this->makeHttpPostRequest($url, $data, $storeId);
-        $this->logger->info('Webhooks sent');
     }
 
     private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using the webhook key saved in config
         $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-        $this->logger->info('Webhooks - key: ' . $webhookKey);
-//        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
         // Generate the HMAC-SHA256 hash as raw binary data
         $rawSignature = hash_hmac('sha256', $storeId, $webhookKey, true);
 
@@ -94,7 +77,6 @@ abstract class OrderWebhookBase implements ObserverInterface
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
-        $this->logger->info('Webhooks payload: ' . $payloadJson);
     }
 
     private function getWebhookUrl(): string
@@ -107,25 +89,4 @@ abstract class OrderWebhookBase implements ObserverInterface
         $storeId = $this->storeManager->getStore()->getId();
         return $storeId;
     }
-
-    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;
-    }
 }
-- 
GitLab


From d40f977ba30ea60d486f824ad10de0f895b807ad Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 11:47:31 +0200
Subject: [PATCH 21/56] change shipping description

---
 Observer/ModifyShippingDescription.php | 70 ++++++++++++++++++++++++++
 etc/events.xml                         |  5 ++
 2 files changed, 75 insertions(+)
 create mode 100644 Observer/ModifyShippingDescription.php

diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
new file mode 100644
index 0000000..3c19823
--- /dev/null
+++ b/Observer/ModifyShippingDescription.php
@@ -0,0 +1,70 @@
+<?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();
+
+        // Log the original shipping description
+        $this->logger->info('Original Shipping Description: ' . $shippingDescription);
+
+        // Get the shipping method used in the order (e.g., bobgo_10303_39_1)
+        $shippingMethod = $order->getShippingMethod();
+
+        // Get the method title from the shipping description (which might already include the title)
+        $methodTitle = $this->extractMethodTitle($shippingDescription);
+
+        // Log the method title for debugging
+        $this->logger->info('Extracted Method Title: ' . $methodTitle);
+
+        // Set the new dynamic shipping description based only on MethodTitle
+        $newDescription = $methodTitle;
+
+        // Update the shipping description in the order
+        $order->setShippingDescription($newDescription);
+
+        // Optionally log the new shipping description
+        $this->logger->info('Updated Shipping Description: ' . $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;
+    }
+
+}
diff --git a/etc/events.xml b/etc/events.xml
index d4d14f1..a6fab5c 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -3,4 +3,9 @@
     <event name="sales_order_save_after">
         <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
     </event>
+    <!-- app/code/Vendor/Module/etc/events.xml -->
+    <event name="sales_order_place_before">
+        <observer name="modify_shipping_description" instance="BobGroup\BobGo\Observer\ModifyShippingDescription"/>
+    </event>
+
 </config>
-- 
GitLab


From 57d26adc7c75cc5c482206f2e4fa71f282e6ab78 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 13:38:30 +0200
Subject: [PATCH 22/56] change shipping description

---
 Model/Carrier/BobGo.php                | 15 ++++-----------
 Model/Carrier/UData.php                |  2 +-
 Observer/ConfigChangeObserver.php      |  4 +---
 Observer/ModifyShippingDescription.php | 12 ------------
 Observer/OrderWebhookBase.php          |  2 +-
 5 files changed, 7 insertions(+), 28 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index fdb7283..332ab93 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1360,7 +1360,7 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
             $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);
+            $this->curl->addHeader('x-m-webhook-signature', $signature);
 
             $payloadJson = json_encode($payload);
             $this->_logger->info('Webhooks payload: ' . $payloadJson);
@@ -1377,20 +1377,13 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
 
             $response = json_decode($responseBody, true);
 
-            if ($statusCode == 200 && isset($response['success']) && $response['success'] === true) {
-                $this->_logger->info('Webhook validation successful.');
-//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
-                return true;
-            } else {
-                $this->_logger->error('Webhook validation failed: ' . ($response['message'] ?? 'Unknown error'));
-//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
-                return false;
+            if ($statusCode != 200) {
+                throw new LocalizedException(__('Status code from BobGo: %1', $statusCode));
             }
         } catch (\Exception $e) {
-            $this->_logger->error('Webhook validation exception: ' . $e->getMessage());
-//            throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
             return false;
         }
+        return true;
     }
 
 }
diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index a7e5d2e..adf83a2 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
 }
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 9cbde5d..8362feb 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -73,10 +73,8 @@ class ConfigChangeObserver implements ObserverInterface
         }
 
         // Test for webhooks
-        if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
-            $this->logger->info('Webhooks test start: ');
+        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();
-            $this->logger->info('Webhooks test end: ' . $result);
 
             if ($this->bobGo->isWebhookEnabled()) {
                 if ($result) {
diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
index 3c19823..2684798 100644
--- a/Observer/ModifyShippingDescription.php
+++ b/Observer/ModifyShippingDescription.php
@@ -25,26 +25,14 @@ class ModifyShippingDescription implements ObserverInterface
         // Get the current shipping description
         $shippingDescription = $order->getShippingDescription();
 
-        // Log the original shipping description
-        $this->logger->info('Original Shipping Description: ' . $shippingDescription);
-
-        // Get the shipping method used in the order (e.g., bobgo_10303_39_1)
-        $shippingMethod = $order->getShippingMethod();
-
         // Get the method title from the shipping description (which might already include the title)
         $methodTitle = $this->extractMethodTitle($shippingDescription);
 
-        // Log the method title for debugging
-        $this->logger->info('Extracted Method Title: ' . $methodTitle);
-
         // Set the new dynamic shipping description based only on MethodTitle
         $newDescription = $methodTitle;
 
         // Update the shipping description in the order
         $order->setShippingDescription($newDescription);
-
-        // Optionally log the new shipping description
-        $this->logger->info('Updated Shipping Description: ' . $newDescription);
     }
 
     /**
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 6a5163f..75767cc 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -66,7 +66,7 @@ abstract class OrderWebhookBase implements ObserverInterface
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->addHeader('X-M-Webhook-Signature', $signature);
+        $this->curl->addHeader('x-m-webhook-signature', $signature);
 
         // Perform the API request
         $payloadJson = json_encode($data);
-- 
GitLab


From b0265f41023e1074c06cc45144ccd178ddb27129 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 14:09:45 +0200
Subject: [PATCH 23/56] cleanup

---
 Model/Carrier/BobGo.php                | 46 +++++++++++---------------
 Observer/ModifyShippingDescription.php |  4 +--
 Observer/OrderWebhookBase.php          | 27 ++-------------
 3 files changed, 23 insertions(+), 54 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 332ab93..67c7f0f 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1335,14 +1335,8 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE
         );
 
-        $isEnabled = $this->scopeConfig->getValue(
-            'carriers/bobgo/enable_webhooks',
-            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-        );
-
         // Convert the string to a boolean value
-        $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
-
+        $isEnabled = $this->isWebhookEnabled();
 
         $storeId = strval($this->_storeManager->getStore()->getId());
 
@@ -1354,28 +1348,9 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         ];
 
         try {
-            // 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($payload);
-            $this->_logger->info('Webhooks payload: ' . $payloadJson);
-            if ($payloadJson === false) {
-                throw new \RuntimeException('Failed to encode payload to JSON.');
-            }
-
-            $this->curl->addHeader('Content-Type', 'application/json');
-            $this->curl->post($this->getWebhookUrl(), $payloadJson);
+            $this->encodeWebhookAndPostRequest($this->getWebhookUrl(), $payload, $storeId, $webhookKey);
             $statusCode = $this->curl->getStatus();
-            $this->_logger->info('Webhooks statuscode: ' . $statusCode);
             $responseBody = $this->curl->getBody();
-            $this->_logger->info('Webhooks response: ' . $responseBody);
-
-            $response = json_decode($responseBody, true);
 
             if ($statusCode != 200) {
                 throw new LocalizedException(__('Status code from BobGo: %1', $statusCode));
@@ -1386,4 +1361,21 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         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);
+    }
 }
diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
index 2684798..2e443af 100644
--- a/Observer/ModifyShippingDescription.php
+++ b/Observer/ModifyShippingDescription.php
@@ -25,10 +25,10 @@ class ModifyShippingDescription implements ObserverInterface
         // Get the current shipping description
         $shippingDescription = $order->getShippingDescription();
 
-        // Get the method title from the shipping description (which might already include the title)
+        // Get the method title from the shipping description
         $methodTitle = $this->extractMethodTitle($shippingDescription);
 
-        // Set the new dynamic shipping description based only on MethodTitle
+        // Set the new shipping description based only on MethodTitle
         $newDescription = $methodTitle;
 
         // Update the shipping description in the order
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 75767cc..62988c4 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -50,33 +50,10 @@ abstract class OrderWebhookBase implements ObserverInterface
             'webhooks_enabled' => true, // If we get to this point webhooks are enabled
         ];
 
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
         // Generate the signature using the webhook key saved in config
         $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-        // 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);
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
+        // Send the webhook
+        $this->bobGo->encodeWebhookAndPostRequest($url, $data, $storeId, $webhookKey);
     }
 
     private function getWebhookUrl(): string
-- 
GitLab


From e841e5b6ce80fabe6d185377031c6072e8dd2c7d Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 14 Oct 2024 14:34:28 +0200
Subject: [PATCH 24/56] consumer secret key as webhook key

---
 Observer/ConfigChangeObserver.php | 3 +--
 etc/adminhtml/system.xml          | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 8362feb..efc0179 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -84,8 +84,7 @@ class ConfigChangeObserver implements ObserverInterface
                 } else {
                     $this->messageManager->addErrorMessage(
                         __('Webhook validation failed. Please check your internet connection
-                        and get the webhook key for your channel on Bob Go sales channels page.
-                        https://my.bobgo.co.za/sales-channels')
+                        and use your Bob Go integration consumer secret key for webhook validation.')
                     );
                 }
             }
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 3f4b31f..7aae293 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -39,7 +39,7 @@
                 <!-- Webhook Key Input Field -->
                 <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Webhook key</label>
-                    <comment>Enter the webhook key for authentication.</comment>
+                    <comment>Enter Bob Go integration consumer secret key for webhook authentication.</comment>
                     <depends>
                         <field id="enable_webhooks">1</field>
                     </depends>
-- 
GitLab


From 500707307c24ff55d83719d1fbd929a51f59be90 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 27 Aug 2024 11:28:10 +0200
Subject: [PATCH 25/56] Start webhook implementation

---
 Model/Carrier/UData.php         |   7 ++
 Observer/OrderCreateWebhook.php | 119 ++++++++++++++++++++++++++++++++
 Observer/OrderUpdateWebhook.php |  76 ++++++++++++++++++++
 etc/events.xml                  |   6 ++
 etc/frontend/di.xml             |   8 +++
 5 files changed, 216 insertions(+)
 create mode 100644 Observer/OrderCreateWebhook.php
 create mode 100644 Observer/OrderUpdateWebhook.php

diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index d173baa..a7e5d2e 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -20,4 +20,11 @@ class UData
      * @var string
      */
     public const RATES_ENDPOINT = 'https://api.dev.bobgo.co.za/rates-at-checkout/magento';
+
+    /**
+     * Order create/update webhook URL
+     *
+     * @var string
+     */
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
new file mode 100644
index 0000000..f301cc8
--- /dev/null
+++ b/Observer/OrderCreateWebhook.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use Magento\Framework\Event\Observer;
+use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use BobGroup\BobGo\Model\Carrier\UData;
+use Psr\Log\LoggerInterface;
+use Magento\Store\Model\StoreManagerInterface;
+
+class OrderCreateWebhook implements ObserverInterface
+{
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl; // Initialize the Curl instance
+        $this->storeManager = $storeManager;
+    }
+
+    public function execute(Observer $observer)
+    {
+        $this->logger->info('OrderCreateWebhook: execute method started');
+
+        $order = $observer->getEvent()->getOrder();
+        if (!$order) {
+            $this->logger->error('OrderCreateWebhook: No order object found in observer');
+            return;
+        }
+
+        // Log order creation data
+        $this->logger->info('Order Created:', ['order_id' => $order->getId(), 'order_data' => $order->getData()]);
+
+        // Extract order data and send to the webhook URL
+        $this->sendWebhook($order, 'order_created');
+
+        $this->logger->info('OrderCreateWebhook: execute method finished');
+    }
+
+    private function sendWebhook($order, $eventType)
+    {
+        $this->logger->info('OrderCreateWebhook: sendWebhook method started');
+
+        // Webhook URL
+        $url = $this->getWebhookUrl();
+        $this->logger->info('OrderCreateWebhook: Webhook URL', ['url' => $url]);
+
+        // Get Store UUID and add to query parameters
+        $storeUuid = $this->getStoreUuid();
+        $this->logger->info('UUID: ', ['uuid' => $storeUuid]);
+        $url .= '?channel=' . urlencode($storeUuid);
+        $this->logger->info('Webhook URL', ['url' => $url]);
+
+        // Prepare payload
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'order_data' => $order->getData()
+        ];
+
+        // Log webhook payload
+        $this->logger->info('Sending Webhook:', ['url' => $url, 'payload' => $data]);
+
+        // Send the webhook
+        $this->makeHttpPostRequest($url, $data);
+
+        $this->logger->info('OrderCreateWebhook: sendWebhook method finished');
+    }
+
+
+    private function makeHttpPostRequest($url, $data)
+    {
+        $this->logger->info('URL:', ['url' => $url]);
+        $this->logger->info('Data:', ['data' => $data]);
+
+        // Perform the API request
+        $payloadJson = json_encode($data);
+        if ($payloadJson === false) {
+            $this->logger->error('Payload Webhook failed: Unable to encode JSON.');
+            throw new \RuntimeException('Failed to encode payload to JSON.');
+        }
+
+        $this->logger->info('Payload Webhook:', ['response' => $payloadJson]);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->post($url, $payloadJson);
+        $statusCode = $this->curl->getStatus();
+        $responseBody = $this->curl->getBody();
+
+        // Log status code and response body
+        $this->logger->info('Webhook Response Status:', ['status' => $statusCode]);
+        $this->logger->info('Webhook Response Body:', ['response' => $responseBody]);
+
+        // Decode the response
+        $response = json_decode($responseBody, true);
+        if (json_last_error() !== JSON_ERROR_NONE) {
+            $this->logger->error('Failed to decode webhook response:', ['error' => json_last_error_msg()]);
+        } else {
+            $this->logger->info('Response Webhook:', ['response' => $response]);
+        }
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreUuid(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+        //return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+}
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
new file mode 100644
index 0000000..ad2a4ad
--- /dev/null
+++ b/Observer/OrderUpdateWebhook.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use Magento\Framework\Event\Observer;
+use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use Magento\Store\Model\StoreManagerInterface;
+use BobGroup\BobGo\Model\Carrier\UData;
+use Psr\Log\LoggerInterface;
+
+class OrderUpdateWebhook implements ObserverInterface
+{
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl;
+        $this->storeManager = $storeManager;
+    }
+
+    public function execute(Observer $observer)
+    {
+        $order = $observer->getEvent()->getOrder();
+        if (!$order) {
+            return;
+        }
+
+        $this->sendWebhook($order, 'order_updated');
+    }
+
+    private function sendWebhook($order, $eventType)
+    {
+        $url = $this->getWebhookUrl();
+
+        // Get Store UUID and add to query parameters
+        $storeUuid = $this->getStoreUuid();
+        $url .= '?channel=' . urlencode($storeUuid);
+
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'order_data' => $order->getData()
+        ];
+
+        $this->makeHttpPostRequest($url, $data);
+    }
+
+    private function makeHttpPostRequest($url, $data)
+    {
+        $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);
+        $statusCode = $this->curl->getStatus();
+        $responseBody = $this->curl->getBody();
+
+        $response = json_decode($responseBody, true);
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreUuid(): string
+    {
+        return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+}
diff --git a/etc/events.xml b/etc/events.xml
index bfb5e96..3e71bc3 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -1,3 +1,9 @@
 <?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_order_place_after">
+        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
+    </event>
+    <event name="sales_order_save_after">
+        <observer name="order_update_webhook" instance="BobGroup\BobGo\Observer\OrderUpdateWebhook"/>
+    </event>
 </config>
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
index bc1aaeb..25a80a9 100644
--- a/etc/frontend/di.xml
+++ b/etc/frontend/di.xml
@@ -13,4 +13,12 @@
             <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
         </arguments>
     </type>
+    <type name="BobGroup\BobGo\Observer\OrderCreateWebhook">
+        <arguments>
+            <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument>
+            <argument name="curl" xsi:type="object">Magento\Framework\HTTP\Client\Curl</argument>
+            <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface</argument>
+        </arguments>
+    </type>
+
 </config>
-- 
GitLab


From a0918ae512892d1857097913831e7865bd005ad7 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 28 Aug 2024 14:18:32 +0200
Subject: [PATCH 26/56] Add to webhooks

---
 Observer/OrderCreateWebhook.php | 78 ++++++++++++++++-----------------
 Observer/OrderUpdateWebhook.php | 52 +++++++++++++++++++---
 2 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index f301cc8..3f29ba7 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -18,91 +18,83 @@ class OrderCreateWebhook implements ObserverInterface
     public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
     {
         $this->logger = $logger;
-        $this->curl = $curl; // Initialize the Curl instance
+        $this->curl = $curl;
         $this->storeManager = $storeManager;
     }
 
     public function execute(Observer $observer)
     {
-        $this->logger->info('OrderCreateWebhook: execute method started');
-
         $order = $observer->getEvent()->getOrder();
         if (!$order) {
-            $this->logger->error('OrderCreateWebhook: No order object found in observer');
+            //$this->logger->error('OrderCreateWebhook: No order object found in observer');
             return;
         }
 
-        // Log order creation data
-        $this->logger->info('Order Created:', ['order_id' => $order->getId(), 'order_data' => $order->getData()]);
-
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_created');
-
-        $this->logger->info('OrderCreateWebhook: execute method finished');
+        $this->sendWebhook($order, 'order_create');
     }
 
     private function sendWebhook($order, $eventType)
     {
-        $this->logger->info('OrderCreateWebhook: sendWebhook method started');
-
         // Webhook URL
         $url = $this->getWebhookUrl();
-        $this->logger->info('OrderCreateWebhook: Webhook URL', ['url' => $url]);
 
-        // Get Store UUID and add to query parameters
-        $storeUuid = $this->getStoreUuid();
-        $this->logger->info('UUID: ', ['uuid' => $storeUuid]);
-        $url .= '?channel=' . urlencode($storeUuid);
-        $this->logger->info('Webhook URL', ['url' => $url]);
+        // Extract order items
+        $itemsData = [];
+        foreach ($order->getAllItems() as $item) {
+            $itemsData[] = $item->getData();
+        }
+
+        // Extract shipping address
+        $shippingAddress = $order->getShippingAddress();
+        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
+
+        // Extract billing address
+        $billingAddress = $order->getBillingAddress();
+        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
-            'order_data' => $order->getData()
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $this->getStoreId(),
+            'order_data' => $order->getData(),
+            'items' => $itemsData,
+            'shipping_address' => $shippingAddressData,
+            'billing_address'  => $billingAddressData,
         ];
 
-        // Log webhook payload
-        $this->logger->info('Sending Webhook:', ['url' => $url, 'payload' => $data]);
-
         // Send the webhook
         $this->makeHttpPostRequest($url, $data);
-
-        $this->logger->info('OrderCreateWebhook: sendWebhook method finished');
     }
 
-
     private function makeHttpPostRequest($url, $data)
     {
-        $this->logger->info('URL:', ['url' => $url]);
-        $this->logger->info('Data:', ['data' => $data]);
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'your_secret_key';
+        $payloadJson = json_encode($data);
+        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->addHeader('X-M-Webhook-Signature', $signature); // Add your custom header here
 
         // Perform the API request
         $payloadJson = json_encode($data);
         if ($payloadJson === false) {
-            $this->logger->error('Payload Webhook failed: Unable to encode JSON.');
+            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
             throw new \RuntimeException('Failed to encode payload to JSON.');
         }
 
-        $this->logger->info('Payload Webhook:', ['response' => $payloadJson]);
-
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
         $statusCode = $this->curl->getStatus();
         $responseBody = $this->curl->getBody();
 
-        // Log status code and response body
-        $this->logger->info('Webhook Response Status:', ['status' => $statusCode]);
-        $this->logger->info('Webhook Response Body:', ['response' => $responseBody]);
-
         // Decode the response
         $response = json_decode($responseBody, true);
-        if (json_last_error() !== JSON_ERROR_NONE) {
-            $this->logger->error('Failed to decode webhook response:', ['error' => json_last_error_msg()]);
-        } else {
-            $this->logger->info('Response Webhook:', ['response' => $response]);
-        }
     }
 
     private function getWebhookUrl(): string
@@ -110,10 +102,14 @@ class OrderCreateWebhook implements ObserverInterface
         return UData::WEBHOOK_URL;
     }
 
-    private function getStoreUuid(): string
+    private function getStoreId(): string
     {
         $storeId = $this->storeManager->getStore()->getId();
         return $storeId;
-        //return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+    }
+
+    private function getStoreUrl(): string
+    {
+        return $this->storeManager->getStore()->getBaseUrl();
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index ad2a4ad..6d6b43a 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -5,9 +5,9 @@ namespace BobGroup\BobGo\Observer;
 use Magento\Framework\Event\Observer;
 use Magento\Framework\Event\ObserverInterface;
 use Magento\Framework\HTTP\Client\Curl;
-use Magento\Store\Model\StoreManagerInterface;
 use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
+use Magento\Store\Model\StoreManagerInterface;
 
 class OrderUpdateWebhook implements ObserverInterface
 {
@@ -29,38 +29,70 @@ class OrderUpdateWebhook implements ObserverInterface
             return;
         }
 
+        // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_updated');
     }
 
     private function sendWebhook($order, $eventType)
     {
+        // Webhook URL
         $url = $this->getWebhookUrl();
 
-        // Get Store UUID and add to query parameters
-        $storeUuid = $this->getStoreUuid();
-        $url .= '?channel=' . urlencode($storeUuid);
+        // Extract order items
+        $itemsData = [];
+        foreach ($order->getAllItems() as $item) {
+            $itemsData[] = $item->getData();
+        }
+
+        // Extract shipping address
+        $shippingAddress = $order->getShippingAddress();
+        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
+
+        // Extract billing address
+        $billingAddress = $order->getBillingAddress();
+        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
-            'order_data' => $order->getData()
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $this->getStoreId(),
+            'order_data' => $order->getData(),
+            'items' => $itemsData,
+            'shipping_address' => $shippingAddressData,
+            'billing_address'  => $billingAddressData,
         ];
 
+        // Send the webhook
         $this->makeHttpPostRequest($url, $data);
     }
 
     private function makeHttpPostRequest($url, $data)
     {
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'your_secret_key';
+        $payloadJson = json_encode($data);
+        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->addHeader('X-M-Webhook-Signature', $signature); // Add your custom header here
+
+        // Perform the API request
         $payloadJson = json_encode($data);
         if ($payloadJson === false) {
+            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
             throw new \RuntimeException('Failed to encode payload to JSON.');
         }
 
+        // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
         $statusCode = $this->curl->getStatus();
         $responseBody = $this->curl->getBody();
 
+        // Decode the response
         $response = json_decode($responseBody, true);
     }
 
@@ -69,8 +101,14 @@ class OrderUpdateWebhook implements ObserverInterface
         return UData::WEBHOOK_URL;
     }
 
-    private function getStoreUuid(): string
+    private function getStoreId(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+    }
+
+    private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getConfig('general/store_information/store_id');
+        return $this->storeManager->getStore()->getBaseUrl();
     }
 }
-- 
GitLab


From 524ce233f070724f1c97542e4baae10f786a19ad Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 08:14:04 +0200
Subject: [PATCH 27/56] Clean identifier url

---
 Observer/OrderCreateWebhook.php | 18 +++++++++++++++++-
 Observer/OrderUpdateWebhook.php | 18 +++++++++++++++++-
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 3f29ba7..010bec5 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -110,6 +110,22 @@ class OrderCreateWebhook implements ObserverInterface
 
     private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getBaseUrl();
+        $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;
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 6d6b43a..01b7695 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -109,6 +109,22 @@ class OrderUpdateWebhook implements ObserverInterface
 
     private function getStoreUrl(): string
     {
-        return $this->storeManager->getStore()->getBaseUrl();
+        $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;
     }
 }
-- 
GitLab


From b0af6b717d878ae72d13e1d691a679fd02472a6a Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 10:55:10 +0200
Subject: [PATCH 28/56] webhook signature

---
 Observer/OrderCreateWebhook.php | 28 +++++++++++++++++-----------
 Observer/OrderUpdateWebhook.php | 25 +++++++++++++++----------
 2 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 010bec5..cf90443 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -31,7 +31,7 @@ class OrderCreateWebhook implements ObserverInterface
         }
 
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_create');
+        $this->sendWebhook($order, 'order_created');
     }
 
     private function sendWebhook($order, $eventType)
@@ -53,28 +53,34 @@ class OrderCreateWebhook implements ObserverInterface
         $billingAddress = $order->getBillingAddress();
         $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        $storeId = $this->getStoreId();
+
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
             'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $this->getStoreId(),
-            'order_data' => $order->getData(),
-            'items' => $itemsData,
-            'shipping_address' => $shippingAddressData,
-            'billing_address'  => $billingAddressData,
+            'store_id' => $storeId,
+            //'order_data' => $order->getData(),
+            //'items' => $itemsData,
+            //'shipping_address' => $shippingAddressData,
+            //'billing_address'  => $billingAddressData,
         ];
 
         // Send the webhook
-        $this->makeHttpPostRequest($url, $data);
+        $this->makeHttpPostRequest($url, $data, $storeId);
     }
 
-    private function makeHttpPostRequest($url, $data)
+    private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'your_secret_key';
-        $payloadJson = json_encode($data);
-        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+
+        // Encode the binary data in Base64
+        $signature = base64_encode($rawSignature);
+
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 01b7695..095c887 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -52,28 +52,33 @@ class OrderUpdateWebhook implements ObserverInterface
         $billingAddress = $order->getBillingAddress();
         $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
 
+        $storeId = $this->getStoreId();
+
         // Prepare payload
         $data = [
             'event' => $eventType,
             'order_id' => $order->getId(),
             'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $this->getStoreId(),
-            'order_data' => $order->getData(),
-            'items' => $itemsData,
-            'shipping_address' => $shippingAddressData,
-            'billing_address'  => $billingAddressData,
+            'store_id' => $storeId,
+            //'order_data' => $order->getData(),
+            //'items' => $itemsData,
+            //'shipping_address' => $shippingAddressData,
+            //'billing_address'  => $billingAddressData,
         ];
 
         // Send the webhook
-        $this->makeHttpPostRequest($url, $data);
+        $this->makeHttpPostRequest($url, $data, $storeId);
     }
 
-    private function makeHttpPostRequest($url, $data)
+    private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'your_secret_key';
-        $payloadJson = json_encode($data);
-        $signature = hash_hmac('sha256', $payloadJson, $secretKey);
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+
+        // Encode the binary data in Base64
+        $signature = base64_encode($rawSignature);
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
-- 
GitLab


From 3e0d8153cfe473fe1d374cdfa22833adeadf17e4 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 11:46:53 +0200
Subject: [PATCH 29/56] use sahred functions for webhooks

---
 Observer/OrderCreateWebhook.php | 104 +-------------------------------
 Observer/OrderUpdateWebhook.php | 102 +------------------------------
 Observer/OrderWebhookBase.php   |  85 ++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 204 deletions(-)
 create mode 100644 Observer/OrderWebhookBase.php

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index cf90443..1b93779 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -9,7 +9,7 @@ use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
-class OrderCreateWebhook implements ObserverInterface
+class OrderCreateWebhook extends OrderWebhookBase
 {
     protected Curl $curl;
     protected LoggerInterface $logger;
@@ -26,112 +26,10 @@ class OrderCreateWebhook implements ObserverInterface
     {
         $order = $observer->getEvent()->getOrder();
         if (!$order) {
-            //$this->logger->error('OrderCreateWebhook: No order object found in observer');
             return;
         }
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_created');
     }
-
-    private function sendWebhook($order, $eventType)
-    {
-        // Webhook URL
-        $url = $this->getWebhookUrl();
-
-        // Extract order items
-        $itemsData = [];
-        foreach ($order->getAllItems() as $item) {
-            $itemsData[] = $item->getData();
-        }
-
-        // Extract shipping address
-        $shippingAddress = $order->getShippingAddress();
-        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
-
-        // Extract billing address
-        $billingAddress = $order->getBillingAddress();
-        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
-
-        $storeId = $this->getStoreId();
-
-        // Prepare payload
-        $data = [
-            'event' => $eventType,
-            'order_id' => $order->getId(),
-            'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $storeId,
-            //'order_data' => $order->getData(),
-            //'items' => $itemsData,
-            //'shipping_address' => $shippingAddressData,
-            //'billing_address'  => $billingAddressData,
-        ];
-
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
-        // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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); // Add your custom header here
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
-        $statusCode = $this->curl->getStatus();
-        $responseBody = $this->curl->getBody();
-
-        // Decode the response
-        $response = json_decode($responseBody, true);
-    }
-
-    private function getWebhookUrl(): string
-    {
-        return UData::WEBHOOK_URL;
-    }
-
-    private function getStoreId(): string
-    {
-        $storeId = $this->storeManager->getStore()->getId();
-        return $storeId;
-    }
-
-    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;
-    }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 095c887..03b96cb 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -9,7 +9,7 @@ use BobGroup\BobGo\Model\Carrier\UData;
 use Psr\Log\LoggerInterface;
 use Magento\Store\Model\StoreManagerInterface;
 
-class OrderUpdateWebhook implements ObserverInterface
+class OrderUpdateWebhook extends OrderWebhookBase
 {
     protected Curl $curl;
     protected LoggerInterface $logger;
@@ -32,104 +32,4 @@ class OrderUpdateWebhook implements ObserverInterface
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order, 'order_updated');
     }
-
-    private function sendWebhook($order, $eventType)
-    {
-        // Webhook URL
-        $url = $this->getWebhookUrl();
-
-        // Extract order items
-        $itemsData = [];
-        foreach ($order->getAllItems() as $item) {
-            $itemsData[] = $item->getData();
-        }
-
-        // Extract shipping address
-        $shippingAddress = $order->getShippingAddress();
-        $shippingAddressData = $shippingAddress ? $shippingAddress->getData() : [];
-
-        // Extract billing address
-        $billingAddress = $order->getBillingAddress();
-        $billingAddressData = $billingAddress ? $billingAddress->getData() : [];
-
-        $storeId = $this->getStoreId();
-
-        // Prepare payload
-        $data = [
-            'event' => $eventType,
-            'order_id' => $order->getId(),
-            'channel_identifier' => $this->getStoreUrl(),
-            'store_id' => $storeId,
-            //'order_data' => $order->getData(),
-            //'items' => $itemsData,
-            //'shipping_address' => $shippingAddressData,
-            //'billing_address'  => $billingAddressData,
-        ];
-
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
-        // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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); // Add your custom header here
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            //$this->logger->error('Payload Webhook failed: Unable to encode JSON.');
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
-        $statusCode = $this->curl->getStatus();
-        $responseBody = $this->curl->getBody();
-
-        // Decode the response
-        $response = json_decode($responseBody, true);
-    }
-
-    private function getWebhookUrl(): string
-    {
-        return UData::WEBHOOK_URL;
-    }
-
-    private function getStoreId(): string
-    {
-        $storeId = $this->storeManager->getStore()->getId();
-        return $storeId;
-    }
-
-    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;
-    }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
new file mode 100644
index 0000000..9f2e83f
--- /dev/null
+++ b/Observer/OrderWebhookBase.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace BobGroup\BobGo\Observer;
+
+use BobGroup\BobGo\Model\Carrier\UData;
+use Magento\Framework\Event\ObserverInterface;
+
+abstract class OrderWebhookBase implements ObserverInterface
+{
+    protected function sendWebhook($order, $eventType)
+    {
+        // Webhook URL
+        $url = $this->getWebhookUrl();
+
+        $storeId = $this->getStoreId();
+
+        // Prepare payload
+        $data = [
+            'event' => $eventType,
+            'order_id' => $order->getId(),
+            'channel_identifier' => $this->getStoreUrl(),
+            'store_id' => $storeId,
+        ];
+
+        // Send the webhook
+        $this->makeHttpPostRequest($url, $data, $storeId);
+    }
+
+    private function makeHttpPostRequest($url, $data, $storeId)
+    {
+        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
+        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the HMAC-SHA256 hash as raw binary data
+        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, 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);
+
+        // Perform the API request
+        $payloadJson = json_encode($data);
+        if ($payloadJson === false) {
+            throw new \RuntimeException('Failed to encode payload to JSON.');
+        }
+
+        // Set headers and post the data
+        $this->curl->addHeader('Content-Type', 'application/json');
+        $this->curl->post($url, $payloadJson);
+    }
+
+    private function getWebhookUrl(): string
+    {
+        return UData::WEBHOOK_URL;
+    }
+
+    private function getStoreId(): string
+    {
+        $storeId = $this->storeManager->getStore()->getId();
+        return $storeId;
+    }
+
+    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;
+    }
+}
-- 
GitLab


From d061262a822de9a89f7de139665186c2e69b6304 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 12:00:12 +0200
Subject: [PATCH 30/56] cleanup

---
 Observer/OrderCreateWebhook.php | 16 ----------------
 Observer/OrderUpdateWebhook.php | 16 ----------------
 Observer/OrderWebhookBase.php   | 14 ++++++++++++++
 3 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 1b93779..678f2de 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -3,25 +3,9 @@
 namespace BobGroup\BobGo\Observer;
 
 use Magento\Framework\Event\Observer;
-use Magento\Framework\Event\ObserverInterface;
-use Magento\Framework\HTTP\Client\Curl;
-use BobGroup\BobGo\Model\Carrier\UData;
-use Psr\Log\LoggerInterface;
-use Magento\Store\Model\StoreManagerInterface;
 
 class OrderCreateWebhook extends OrderWebhookBase
 {
-    protected Curl $curl;
-    protected LoggerInterface $logger;
-    protected StoreManagerInterface $storeManager;
-
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
-    {
-        $this->logger = $logger;
-        $this->curl = $curl;
-        $this->storeManager = $storeManager;
-    }
-
     public function execute(Observer $observer)
     {
         $order = $observer->getEvent()->getOrder();
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
index 03b96cb..3074bdd 100644
--- a/Observer/OrderUpdateWebhook.php
+++ b/Observer/OrderUpdateWebhook.php
@@ -3,25 +3,9 @@
 namespace BobGroup\BobGo\Observer;
 
 use Magento\Framework\Event\Observer;
-use Magento\Framework\Event\ObserverInterface;
-use Magento\Framework\HTTP\Client\Curl;
-use BobGroup\BobGo\Model\Carrier\UData;
-use Psr\Log\LoggerInterface;
-use Magento\Store\Model\StoreManagerInterface;
 
 class OrderUpdateWebhook extends OrderWebhookBase
 {
-    protected Curl $curl;
-    protected LoggerInterface $logger;
-    protected StoreManagerInterface $storeManager;
-
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
-    {
-        $this->logger = $logger;
-        $this->curl = $curl;
-        $this->storeManager = $storeManager;
-    }
-
     public function execute(Observer $observer)
     {
         $order = $observer->getEvent()->getOrder();
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 9f2e83f..b17375e 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -4,9 +4,23 @@ namespace BobGroup\BobGo\Observer;
 
 use BobGroup\BobGo\Model\Carrier\UData;
 use Magento\Framework\Event\ObserverInterface;
+use Magento\Framework\HTTP\Client\Curl;
+use Magento\Store\Model\StoreManagerInterface;
+use Psr\Log\LoggerInterface;
 
 abstract class OrderWebhookBase implements ObserverInterface
 {
+    protected Curl $curl;
+    protected LoggerInterface $logger;
+    protected StoreManagerInterface $storeManager;
+
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    {
+        $this->logger = $logger;
+        $this->curl = $curl;
+        $this->storeManager = $storeManager;
+    }
+
     protected function sendWebhook($order, $eventType)
     {
         // Webhook URL
-- 
GitLab


From 8d5a03f71fb188401a264b5519f6862dabb5d47a Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 14:57:11 +0200
Subject: [PATCH 31/56] orderId for both created and updated

---
 Observer/OrderCreateWebhook.php |  2 +-
 Observer/OrderUpdateWebhook.php | 19 -------------------
 Observer/OrderWebhookBase.php   | 23 +++++++++++++++++++++--
 etc/events.xml                  |  5 +----
 4 files changed, 23 insertions(+), 26 deletions(-)
 delete mode 100644 Observer/OrderUpdateWebhook.php

diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 678f2de..74f1ce4 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -14,6 +14,6 @@ class OrderCreateWebhook extends OrderWebhookBase
         }
 
         // Extract order data and send to the webhook URL
-        $this->sendWebhook($order, 'order_created');
+        $this->sendWebhook($order);
     }
 }
diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php
deleted file mode 100644
index 3074bdd..0000000
--- a/Observer/OrderUpdateWebhook.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-namespace BobGroup\BobGo\Observer;
-
-use Magento\Framework\Event\Observer;
-
-class OrderUpdateWebhook 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, 'order_updated');
-    }
-}
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index b17375e..f4ca74d 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -21,17 +21,36 @@ abstract class OrderWebhookBase implements ObserverInterface
         $this->storeManager = $storeManager;
     }
 
-    protected function sendWebhook($order, $eventType)
+    protected function sendWebhook($order)
     {
         // Webhook URL
         $url = $this->getWebhookUrl();
 
         $storeId = $this->getStoreId();
 
+        $orderId = $order->getId();
+
+        // Get the order creation time
+        $createdAt = strtotime($order->getCreatedAt());
+        $currentTime = time();
+
+        // Define a time threshold  to consider the order as newly created
+        $threshold = 5; // 5  seconds
+
+        // Determine the event type based on the creation time
+        if (($currentTime - $createdAt) < $threshold) {
+            $eventType = 'order_created';
+        } else {
+            $eventType = 'order_updated';
+        }
+
+        // Log the event type for debugging purposes
+        $this->logger->info('event: ' . $eventType);
+
         // Prepare payload
         $data = [
             'event' => $eventType,
-            'order_id' => $order->getId(),
+            'order_id' => $orderId,
             'channel_identifier' => $this->getStoreUrl(),
             'store_id' => $storeId,
         ];
diff --git a/etc/events.xml b/etc/events.xml
index 3e71bc3..d4d14f1 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -1,9 +1,6 @@
 <?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_order_place_after">
-        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
-    </event>
     <event name="sales_order_save_after">
-        <observer name="order_update_webhook" instance="BobGroup\BobGo\Observer\OrderUpdateWebhook"/>
+        <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
     </event>
 </config>
-- 
GitLab


From 06c7ec846891a49d6328d541cc176b6e03ca9834 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 14:58:47 +0200
Subject: [PATCH 32/56] cleanup

---
 Observer/OrderWebhookBase.php | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index f4ca74d..eeb106e 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -44,9 +44,6 @@ abstract class OrderWebhookBase implements ObserverInterface
             $eventType = 'order_updated';
         }
 
-        // Log the event type for debugging purposes
-        $this->logger->info('event: ' . $eventType);
-
         // Prepare payload
         $data = [
             'event' => $eventType,
-- 
GitLab


From b07a8cd51af5973048864010869adfd94130ba68 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 29 Aug 2024 15:08:50 +0200
Subject: [PATCH 33/56] change endpoint

---
 Model/Carrier/UData.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index a7e5d2e..adf83a2 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
 }
-- 
GitLab


From eda30797c33a55153a5db5c0f4605b7d1bd0417e Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 2 Oct 2024 15:44:00 +0200
Subject: [PATCH 34/56] triggerWebhookTest

---
 Model/Carrier/BobGo.php           | 87 +++++++++++++++++++++++++++++++
 Model/Carrier/UData.php           |  2 +-
 Observer/ConfigChangeObserver.php | 20 +++++++
 Observer/OrderCreateWebhook.php   |  1 +
 Observer/OrderWebhookBase.php     | 24 +++++++--
 etc/adminhtml/system.xml          | 17 +++++-
 6 files changed, 145 insertions(+), 6 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 2809b13..77b8e88 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -680,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.
      *
@@ -1041,4 +1046,86 @@ 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
+        );
+
+        $isEnabled = $this->scopeConfig->getValue(
+            'carriers/bobgo/enable_webhooks',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+        );
+
+        // Convert the string to a boolean value
+        $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
+
+//        if (!$webhookKey) {
+//            $this->_logger->error('Webhook key not configured.');
+//            return false;
+//        }
+
+        $storeId = strval($this->_storeManager->getStore()->getId());
+
+        $payload = [
+            'event' => 'webhook_validation',
+            'channel_identifier' => $this->getBaseUrl(),
+            'store_id' => $storeId,
+            'webhooks_enabled' => $isEnabled,
+        ];
+
+        try {
+            // 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($payload);
+            $this->_logger->info('Webhooks payload: ' . $payloadJson);
+            if ($payloadJson === false) {
+                throw new \RuntimeException('Failed to encode payload to JSON.');
+            }
+
+            $this->curl->addHeader('Content-Type', 'application/json');
+            $this->curl->post($this->getWebhookUrl(), $payloadJson);
+            $statusCode = $this->curl->getStatus();
+            $this->_logger->info('Webhooks statuscode: ' . $statusCode);
+            $responseBody = $this->curl->getBody();
+            $this->_logger->info('Webhooks response: ' . $responseBody);
+
+            $response = json_decode($responseBody, true);
+
+            if ($statusCode == 200 && isset($response['success']) && $response['success'] === true) {
+                $this->_logger->info('Webhook validation successful.');
+//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+                return true;
+            } else {
+                $this->_logger->error('Webhook validation failed: ' . ($response['message'] ?? 'Unknown error'));
+//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+                return false;
+            }
+        } catch (\Exception $e) {
+            $this->_logger->error('Webhook validation exception: ' . $e->getMessage());
+//            throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
+            return false;
+        }
+    }
+
 }
diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index adf83a2..a7e5d2e 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
 }
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 1b6c072..528dd82 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -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,24 @@ class ConfigChangeObserver implements ObserverInterface
                 }
             }
         }
+
+        // Test for webhooks
+        if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
+//            if ($this->bobGo->isWebhookEnabled()) {
+                $this->logger->info('Webhooks test start: ');
+                $result = $this->bobGo->triggerWebhookTest();
+                $this->logger->info('Webhooks test end: ' . $result);
+
+                if ($result) {
+                    $this->messageManager->addSuccessMessage(
+                        __('Webhook validation successful.')
+                    );
+                } else {
+                    $this->messageManager->addErrorMessage(
+                        __('Webhook validation failed. Please check the webhook key and try again.')
+                    );
+                }
+//            }
+        }
     }
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index 74f1ce4..f605801 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -15,5 +15,6 @@ class OrderCreateWebhook extends OrderWebhookBase
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order);
+        $this->logger->info('Webhooks sent');
     }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index eeb106e..db27d61 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -3,6 +3,7 @@
 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;
@@ -13,18 +14,29 @@ abstract class OrderWebhookBase implements ObserverInterface
     protected Curl $curl;
     protected LoggerInterface $logger;
     protected StoreManagerInterface $storeManager;
+    protected ScopeConfigInterface $scopeConfig;
 
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager)
+    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig)
     {
         $this->logger = $logger;
         $this->curl = $curl;
         $this->storeManager = $storeManager;
+        $this->scopeConfig = $scopeConfig;
     }
 
     protected function sendWebhook($order)
     {
+        $enabled = $this->scopeConfig->getValue('carriers/bobgo/enable_webhooks', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+
+        // Return early if webhooks is disabled
+        if (!$enabled) {
+            $this->logger->info('Webhooks are disabled. Exiting webhook process for order: ' . $order->getIncrementId());
+            return;
+        }
+
         // Webhook URL
         $url = $this->getWebhookUrl();
+        $this->logger->info('Webhooks url: ' . $url);
 
         $storeId = $this->getStoreId();
 
@@ -54,14 +66,17 @@ abstract class OrderWebhookBase implements ObserverInterface
 
         // Send the webhook
         $this->makeHttpPostRequest($url, $data, $storeId);
+        $this->logger->info('Webhooks sent');
     }
 
     private function makeHttpPostRequest($url, $data, $storeId)
     {
-        // Generate the signature using a secret key and the payload (example using HMAC SHA256)
-        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
+        // Generate the signature using the webhook key saved in config
+        $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+        $this->logger->info('Webhooks - key: ' . $webhookKey);
+//        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
         // Generate the HMAC-SHA256 hash as raw binary data
-        $rawSignature = hash_hmac('sha256', $storeId, $secretKey, true);
+        $rawSignature = hash_hmac('sha256', $storeId, $webhookKey, true);
 
         // Encode the binary data in Base64
         $signature = base64_encode($rawSignature);
@@ -79,6 +94,7 @@ abstract class OrderWebhookBase implements ObserverInterface
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
+        $this->logger->info('Webhooks payload: ' . $payloadJson);
     }
 
     private function getWebhookUrl(): string
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 263bc8b..0483f32 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -28,6 +28,22 @@
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                     <comment>Displays the delivery timeframe and additional service level description, as configured on Bob Go.</comment>
                 </field>
+
+                <!-- Enable Webhooks Checkbox -->
+                <field id="enable_webhooks" translate="label" type="select" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Enable webhooks</label>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                    <comment>Enable or disable the webhook functionality for Bob Go.</comment>
+                </field>
+
+                <!-- Webhook Key Input Field -->
+                <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Webhook key</label>
+                    <comment>Enter the webhook key for authentication.</comment>
+                    <depends>
+                        <field id="enable_webhooks">1</field>
+                    </depends>
+                </field>
                     <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                         <label>Enable Track My Order</label>
                         <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
@@ -35,6 +51,5 @@
                     </field>
             </group>
         </section>
-
     </system>
 </config>
-- 
GitLab


From 5c320b2df5db473aa9233772406a303a518213db Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 10:10:05 +0200
Subject: [PATCH 35/56] webhooks test update and webhooks payload

---
 Model/Carrier/BobGo.php           |  4 ---
 Observer/ConfigChangeObserver.php | 14 ++++----
 Observer/OrderCreateWebhook.php   |  1 -
 Observer/OrderWebhookBase.php     | 57 +++++--------------------------
 4 files changed, 17 insertions(+), 59 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 77b8e88..0e750fd 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1074,10 +1074,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         // Convert the string to a boolean value
         $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
 
-//        if (!$webhookKey) {
-//            $this->_logger->error('Webhook key not configured.');
-//            return false;
-//        }
 
         $storeId = strval($this->_storeManager->getStore()->getId());
 
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 528dd82..9cbde5d 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -74,21 +74,23 @@ class ConfigChangeObserver implements ObserverInterface
 
         // Test for webhooks
         if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
-//            if ($this->bobGo->isWebhookEnabled()) {
-                $this->logger->info('Webhooks test start: ');
-                $result = $this->bobGo->triggerWebhookTest();
-                $this->logger->info('Webhooks test end: ' . $result);
+            $this->logger->info('Webhooks test start: ');
+            $result = $this->bobGo->triggerWebhookTest();
+            $this->logger->info('Webhooks test end: ' . $result);
 
+            if ($this->bobGo->isWebhookEnabled()) {
                 if ($result) {
                     $this->messageManager->addSuccessMessage(
                         __('Webhook validation successful.')
                     );
                 } else {
                     $this->messageManager->addErrorMessage(
-                        __('Webhook validation failed. Please check the webhook key and try again.')
+                        __('Webhook validation failed. Please check your internet connection
+                        and get the webhook key for your channel on Bob Go sales channels page.
+                        https://my.bobgo.co.za/sales-channels')
                     );
                 }
-//            }
+            }
         }
     }
 }
diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php
index f605801..74f1ce4 100644
--- a/Observer/OrderCreateWebhook.php
+++ b/Observer/OrderCreateWebhook.php
@@ -15,6 +15,5 @@ class OrderCreateWebhook extends OrderWebhookBase
 
         // Extract order data and send to the webhook URL
         $this->sendWebhook($order);
-        $this->logger->info('Webhooks sent');
     }
 }
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index db27d61..6a5163f 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -8,6 +8,7 @@ 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
 {
@@ -15,66 +16,48 @@ abstract class OrderWebhookBase implements ObserverInterface
     protected LoggerInterface $logger;
     protected StoreManagerInterface $storeManager;
     protected ScopeConfigInterface $scopeConfig;
+    protected $bobGo;
 
-    public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig)
+    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)
     {
-        $enabled = $this->scopeConfig->getValue('carriers/bobgo/enable_webhooks', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-
-        // Return early if webhooks is disabled
-        if (!$enabled) {
-            $this->logger->info('Webhooks are disabled. Exiting webhook process for order: ' . $order->getIncrementId());
+        // Return early if not enabled
+        if (!$this->bobGo->isWebhookEnabled()) {
             return;
         }
 
         // Webhook URL
         $url = $this->getWebhookUrl();
-        $this->logger->info('Webhooks url: ' . $url);
 
         $storeId = $this->getStoreId();
 
         $orderId = $order->getId();
 
-        // Get the order creation time
-        $createdAt = strtotime($order->getCreatedAt());
-        $currentTime = time();
-
-        // Define a time threshold  to consider the order as newly created
-        $threshold = 5; // 5  seconds
-
-        // Determine the event type based on the creation time
-        if (($currentTime - $createdAt) < $threshold) {
-            $eventType = 'order_created';
-        } else {
-            $eventType = 'order_updated';
-        }
-
         // Prepare payload
         $data = [
-            'event' => $eventType,
+            'event' => 'order_updated',
             'order_id' => $orderId,
-            'channel_identifier' => $this->getStoreUrl(),
+            'channel_identifier' => $this->bobGo->getBaseUrl(),
             'store_id' => $storeId,
+            'webhooks_enabled' => true, // If we get to this point webhooks are enabled
         ];
 
         // Send the webhook
         $this->makeHttpPostRequest($url, $data, $storeId);
-        $this->logger->info('Webhooks sent');
     }
 
     private function makeHttpPostRequest($url, $data, $storeId)
     {
         // Generate the signature using the webhook key saved in config
         $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-        $this->logger->info('Webhooks - key: ' . $webhookKey);
-//        $secretKey = 'KaJGW2cxx1-6z_qjGhSq5Hj4qh_OXl0R1tUPurVs66A';
         // Generate the HMAC-SHA256 hash as raw binary data
         $rawSignature = hash_hmac('sha256', $storeId, $webhookKey, true);
 
@@ -94,7 +77,6 @@ abstract class OrderWebhookBase implements ObserverInterface
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
         $this->curl->post($url, $payloadJson);
-        $this->logger->info('Webhooks payload: ' . $payloadJson);
     }
 
     private function getWebhookUrl(): string
@@ -107,25 +89,4 @@ abstract class OrderWebhookBase implements ObserverInterface
         $storeId = $this->storeManager->getStore()->getId();
         return $storeId;
     }
-
-    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;
-    }
 }
-- 
GitLab


From 06e38aa331ba767505d0532026fa55491fc32ba3 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 11:47:31 +0200
Subject: [PATCH 36/56] change shipping description

---
 Observer/ModifyShippingDescription.php | 70 ++++++++++++++++++++++++++
 etc/events.xml                         |  5 ++
 2 files changed, 75 insertions(+)
 create mode 100644 Observer/ModifyShippingDescription.php

diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
new file mode 100644
index 0000000..3c19823
--- /dev/null
+++ b/Observer/ModifyShippingDescription.php
@@ -0,0 +1,70 @@
+<?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();
+
+        // Log the original shipping description
+        $this->logger->info('Original Shipping Description: ' . $shippingDescription);
+
+        // Get the shipping method used in the order (e.g., bobgo_10303_39_1)
+        $shippingMethod = $order->getShippingMethod();
+
+        // Get the method title from the shipping description (which might already include the title)
+        $methodTitle = $this->extractMethodTitle($shippingDescription);
+
+        // Log the method title for debugging
+        $this->logger->info('Extracted Method Title: ' . $methodTitle);
+
+        // Set the new dynamic shipping description based only on MethodTitle
+        $newDescription = $methodTitle;
+
+        // Update the shipping description in the order
+        $order->setShippingDescription($newDescription);
+
+        // Optionally log the new shipping description
+        $this->logger->info('Updated Shipping Description: ' . $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;
+    }
+
+}
diff --git a/etc/events.xml b/etc/events.xml
index d4d14f1..a6fab5c 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -3,4 +3,9 @@
     <event name="sales_order_save_after">
         <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/>
     </event>
+    <!-- app/code/Vendor/Module/etc/events.xml -->
+    <event name="sales_order_place_before">
+        <observer name="modify_shipping_description" instance="BobGroup\BobGo\Observer\ModifyShippingDescription"/>
+    </event>
+
 </config>
-- 
GitLab


From be182ac9d34ebf29e4c4a58108525398176c512d Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 13:38:30 +0200
Subject: [PATCH 37/56] change shipping description

---
 Model/Carrier/BobGo.php                | 15 ++++-----------
 Model/Carrier/UData.php                |  2 +-
 Observer/ConfigChangeObserver.php      |  4 +---
 Observer/ModifyShippingDescription.php | 12 ------------
 Observer/OrderWebhookBase.php          |  2 +-
 5 files changed, 7 insertions(+), 28 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 0e750fd..21144ea 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1091,7 +1091,7 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
             $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);
+            $this->curl->addHeader('x-m-webhook-signature', $signature);
 
             $payloadJson = json_encode($payload);
             $this->_logger->info('Webhooks payload: ' . $payloadJson);
@@ -1108,20 +1108,13 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
 
             $response = json_decode($responseBody, true);
 
-            if ($statusCode == 200 && isset($response['success']) && $response['success'] === true) {
-                $this->_logger->info('Webhook validation successful.');
-//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
-                return true;
-            } else {
-                $this->_logger->error('Webhook validation failed: ' . ($response['message'] ?? 'Unknown error'));
-//                throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
-                return false;
+            if ($statusCode != 200) {
+                throw new LocalizedException(__('Status code from BobGo: %1', $statusCode));
             }
         } catch (\Exception $e) {
-            $this->_logger->error('Webhook validation exception: ' . $e->getMessage());
-//            throw new LocalizedException(__('Rates received but id field is empty or invalid.'));
             return false;
         }
+        return true;
     }
 
 }
diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index a7e5d2e..adf83a2 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -26,5 +26,5 @@ class UData
      *
      * @var string
      */
-    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel';
+    public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel/magento';
 }
diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 9cbde5d..8362feb 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -73,10 +73,8 @@ class ConfigChangeObserver implements ObserverInterface
         }
 
         // Test for webhooks
-        if (is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) {
-            $this->logger->info('Webhooks test start: ');
+        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();
-            $this->logger->info('Webhooks test end: ' . $result);
 
             if ($this->bobGo->isWebhookEnabled()) {
                 if ($result) {
diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
index 3c19823..2684798 100644
--- a/Observer/ModifyShippingDescription.php
+++ b/Observer/ModifyShippingDescription.php
@@ -25,26 +25,14 @@ class ModifyShippingDescription implements ObserverInterface
         // Get the current shipping description
         $shippingDescription = $order->getShippingDescription();
 
-        // Log the original shipping description
-        $this->logger->info('Original Shipping Description: ' . $shippingDescription);
-
-        // Get the shipping method used in the order (e.g., bobgo_10303_39_1)
-        $shippingMethod = $order->getShippingMethod();
-
         // Get the method title from the shipping description (which might already include the title)
         $methodTitle = $this->extractMethodTitle($shippingDescription);
 
-        // Log the method title for debugging
-        $this->logger->info('Extracted Method Title: ' . $methodTitle);
-
         // Set the new dynamic shipping description based only on MethodTitle
         $newDescription = $methodTitle;
 
         // Update the shipping description in the order
         $order->setShippingDescription($newDescription);
-
-        // Optionally log the new shipping description
-        $this->logger->info('Updated Shipping Description: ' . $newDescription);
     }
 
     /**
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 6a5163f..75767cc 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -66,7 +66,7 @@ abstract class OrderWebhookBase implements ObserverInterface
 
         // Set headers and post the data
         $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->addHeader('X-M-Webhook-Signature', $signature);
+        $this->curl->addHeader('x-m-webhook-signature', $signature);
 
         // Perform the API request
         $payloadJson = json_encode($data);
-- 
GitLab


From c86e1b1026ffe7ae2dcaa56c94cc306afe505ebf Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Thu, 3 Oct 2024 14:09:45 +0200
Subject: [PATCH 38/56] cleanup

---
 Model/Carrier/BobGo.php                | 46 +++++++++++---------------
 Observer/ModifyShippingDescription.php |  4 +--
 Observer/OrderWebhookBase.php          | 27 ++-------------
 3 files changed, 23 insertions(+), 54 deletions(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 21144ea..1260bbf 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1066,14 +1066,8 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE
         );
 
-        $isEnabled = $this->scopeConfig->getValue(
-            'carriers/bobgo/enable_webhooks',
-            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-        );
-
         // Convert the string to a boolean value
-        $isEnabled = filter_var($isEnabled, FILTER_VALIDATE_BOOLEAN);
-
+        $isEnabled = $this->isWebhookEnabled();
 
         $storeId = strval($this->_storeManager->getStore()->getId());
 
@@ -1085,28 +1079,9 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         ];
 
         try {
-            // 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($payload);
-            $this->_logger->info('Webhooks payload: ' . $payloadJson);
-            if ($payloadJson === false) {
-                throw new \RuntimeException('Failed to encode payload to JSON.');
-            }
-
-            $this->curl->addHeader('Content-Type', 'application/json');
-            $this->curl->post($this->getWebhookUrl(), $payloadJson);
+            $this->encodeWebhookAndPostRequest($this->getWebhookUrl(), $payload, $storeId, $webhookKey);
             $statusCode = $this->curl->getStatus();
-            $this->_logger->info('Webhooks statuscode: ' . $statusCode);
             $responseBody = $this->curl->getBody();
-            $this->_logger->info('Webhooks response: ' . $responseBody);
-
-            $response = json_decode($responseBody, true);
 
             if ($statusCode != 200) {
                 throw new LocalizedException(__('Status code from BobGo: %1', $statusCode));
@@ -1117,4 +1092,21 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
         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);
+    }
 }
diff --git a/Observer/ModifyShippingDescription.php b/Observer/ModifyShippingDescription.php
index 2684798..2e443af 100644
--- a/Observer/ModifyShippingDescription.php
+++ b/Observer/ModifyShippingDescription.php
@@ -25,10 +25,10 @@ class ModifyShippingDescription implements ObserverInterface
         // Get the current shipping description
         $shippingDescription = $order->getShippingDescription();
 
-        // Get the method title from the shipping description (which might already include the title)
+        // Get the method title from the shipping description
         $methodTitle = $this->extractMethodTitle($shippingDescription);
 
-        // Set the new dynamic shipping description based only on MethodTitle
+        // Set the new shipping description based only on MethodTitle
         $newDescription = $methodTitle;
 
         // Update the shipping description in the order
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 75767cc..62988c4 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -50,33 +50,10 @@ abstract class OrderWebhookBase implements ObserverInterface
             'webhooks_enabled' => true, // If we get to this point webhooks are enabled
         ];
 
-        // Send the webhook
-        $this->makeHttpPostRequest($url, $data, $storeId);
-    }
-
-    private function makeHttpPostRequest($url, $data, $storeId)
-    {
         // Generate the signature using the webhook key saved in config
         $webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-        // 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);
-
-        // Perform the API request
-        $payloadJson = json_encode($data);
-        if ($payloadJson === false) {
-            throw new \RuntimeException('Failed to encode payload to JSON.');
-        }
-
-        // Set headers and post the data
-        $this->curl->addHeader('Content-Type', 'application/json');
-        $this->curl->post($url, $payloadJson);
+        // Send the webhook
+        $this->bobGo->encodeWebhookAndPostRequest($url, $data, $storeId, $webhookKey);
     }
 
     private function getWebhookUrl(): string
-- 
GitLab


From d32f2f6d791338936ff199403a9bc9bbc63f3d71 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 14 Oct 2024 14:34:28 +0200
Subject: [PATCH 39/56] consumer secret key as webhook key

---
 Observer/ConfigChangeObserver.php | 3 +--
 etc/adminhtml/system.xml          | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/Observer/ConfigChangeObserver.php b/Observer/ConfigChangeObserver.php
index 8362feb..efc0179 100644
--- a/Observer/ConfigChangeObserver.php
+++ b/Observer/ConfigChangeObserver.php
@@ -84,8 +84,7 @@ class ConfigChangeObserver implements ObserverInterface
                 } else {
                     $this->messageManager->addErrorMessage(
                         __('Webhook validation failed. Please check your internet connection
-                        and get the webhook key for your channel on Bob Go sales channels page.
-                        https://my.bobgo.co.za/sales-channels')
+                        and use your Bob Go integration consumer secret key for webhook validation.')
                     );
                 }
             }
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 0483f32..4d6ee89 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -39,7 +39,7 @@
                 <!-- Webhook Key Input Field -->
                 <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Webhook key</label>
-                    <comment>Enter the webhook key for authentication.</comment>
+                    <comment>Enter Bob Go integration consumer secret key for webhook authentication.</comment>
                     <depends>
                         <field id="enable_webhooks">1</field>
                     </depends>
-- 
GitLab


From 622419426b4ffdf84d76b0e754a81c9bb7b28fcf Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 16 Oct 2024 08:28:31 +0200
Subject: [PATCH 40/56] merge with dev

---
 etc/adminhtml/system.xml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 4d6ee89..16f3d83 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -44,11 +44,11 @@
                         <field id="enable_webhooks">1</field>
                     </depends>
                 </field>
-                    <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
-                        <label>Enable Track My Order</label>
-                        <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
-                        <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
-                    </field>
+                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
+                    <label>Enable Track My Order</label>
+                    <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                </field>
             </group>
         </section>
     </system>
-- 
GitLab


From 1e1dae675e81ada59e7856e6f486cdbd83ed85bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Thu, 24 Oct 2024 11:25:24 +0200
Subject: [PATCH 41/56] Update the readme

---
 ...ob Go shipping extension for Magento 2.pdf | Bin 0 -> 120911 bytes
 Readme.md                                     |  98 +-----------------
 2 files changed, 2 insertions(+), 96 deletions(-)
 create mode 100644 Installation guide - Bob Go shipping extension for Magento 2.pdf

diff --git a/Installation guide - Bob Go shipping extension for Magento 2.pdf b/Installation guide - Bob Go shipping extension for Magento 2.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..2b410bed7e7f035526b31166ae6838292cd7d39b
GIT binary patch
literal 120911
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

literal 0
HcmV?d00001

diff --git a/Readme.md b/Readme.md
index fcb6fb8..e85f78f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,97 +1,3 @@
-# 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
-- 
GitLab


From 41203e3dbd2035ae1dd8ec709612e4519dcf6991 Mon Sep 17 00:00:00 2001
From: Arno Rossouw <arno@bob.co.za>
Date: Thu, 31 Oct 2024 13:43:55 +0200
Subject: [PATCH 42/56] 5-INFRASTRUCTURE :: husky for auto versioning and build
 on dev when not tag

---
 .distignore       |  11 ++++
 .gitignore        |   2 +
 .gitlab-ci.yml    |  32 +++++-----
 .husky/pre-commit |   1 +
 composer.json     |   2 +-
 etc/module.xml    |   2 +-
 make-zip.sh       | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 package.json      |  19 ++++++
 update-version.js |  36 +++++++++++
 9 files changed, 238 insertions(+), 20 deletions(-)
 create mode 100644 .distignore
 create mode 100644 .gitignore
 create mode 100755 .husky/pre-commit
 create mode 100755 make-zip.sh
 create mode 100644 package.json
 create mode 100644 update-version.js

diff --git a/.distignore b/.distignore
new file mode 100644
index 0000000..e5dc85b
--- /dev/null
+++ b/.distignore
@@ -0,0 +1,11 @@
+*.pdf
+node_modules
+.git
+package.json
+.husky
+package-lock.json
+.distignore
+make-zip.sh
+update-version.js
+.gitlab-ci.yml
+.gitignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..918863b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+*.zip
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index de5cdd5..bc49012 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -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
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..0e8cbb0
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+npm config set git-tag-version false && npm version patch && npm run update-version-files && git add package.json etc/module.xml composer.json
diff --git a/composer.json b/composer.json
index 637ad87..07aad65 100644
--- a/composer.json
+++ b/composer.json
@@ -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.34",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/module.xml b/etc/module.xml
index fe2b36d..d94e8d2 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.0">
+    <module name="BobGroup_BobGo" setup_version="1.0.34">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/make-zip.sh b/make-zip.sh
new file mode 100755
index 0000000..6385066
--- /dev/null
+++ b/make-zip.sh
@@ -0,0 +1,153 @@
+#!/bin/bash
+
+# Exit immediately if a command exits with a non-zero status
+#
+set -e
+
+# Function to log messages
+log() {
+    echo "** $1"
+}
+
+# Function to install jq if not installed
+install_jq() {
+    if command -v jq >/dev/null 2>&1; then
+        log "jq is already installed."
+    else
+        log "jq is not installed. Attempting to install..."
+
+        if [[ "$OSTYPE" == "darwin"* ]]; then
+            if command -v brew >/dev/null 2>&1; then
+                log "Installing jq using Homebrew..."
+                brew install jq
+            else
+                log "Homebrew is not installed. Please install Homebrew first:"
+                log "https://brew.sh/"
+                exit 1
+            fi
+        elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
+            if command -v apt-get >/dev/null 2>&1; then
+                log "Installing jq using apt-get..."
+                sudo apt-get update
+                sudo apt-get install -y jq
+            else
+                log "apt-get not found. Please install jq manually."
+                exit 1
+            fi
+        else
+            log "Unsupported OS. Please install jq manually."
+            exit 1
+        fi
+
+        if command -v jq >/dev/null 2>&1; then
+            log "jq installed successfully."
+        else
+            log "Failed to install jq. Please install it manually."
+            exit 1
+        fi
+    fi
+}
+
+# Function to ensure Perl is installed
+install_perl() {
+    if command -v perl >/dev/null 2>&1; then
+        log "Perl is already installed."
+    else
+        log "Perl is not installed. Please install Perl to proceed."
+        exit 1
+    fi
+}
+
+# Function to extract version using jq
+get_version() {
+    if command -v jq >/dev/null 2>&1; then
+        jq -r '.version' package.json
+    else
+        # Fallback to grep and awk if jq is not available
+        grep '"version":' package.json | head -1 | awk -F'"' '{print $4}'
+    fi
+}
+
+# Function to update the 'Version:' header in bobpay-plugin.php using Perl
+update_version_header() {
+    local VERSION=$1
+    local FILE="composer.json"
+
+    log "Updating 'version:' header in ${FILE} using Perl..."
+
+    # Use Perl to update the 'Version:' line
+    perl -pi -e "s/(\"version\":\s*\")([0-9.]+)(\"\,)/\${1}${VERSION}\"\,/g" "$FILE"
+    log "'version:' header updated to ${VERSION}."
+}
+
+update_define_constant() {
+    local VERSION=$1
+    local FILE="etc/module.xml"
+
+    log "Updating 'version' constant in ${FILE} using Perl..."
+
+    # Use Perl to replace the version constant
+    perl -pi -e "s/(setup_version=\")([^\"]*)/\${1}${VERSION}/g" "$FILE"
+    log "'setup_version' constant updated to ${VERSION}."
+}
+
+# Function to build the plugin
+build_plugin() {
+    log "Building plugin..."
+    npm install
+    log "Plugin built successfully."
+}
+
+# Function to create the zip package
+create_zip() {
+    local VERSION=$1
+    local ZIPNAME="bobgo-magento-plugin.zip"
+    local PACKAGE_DIR="package"
+
+    log "Creating zip file: ${ZIPNAME}..."
+
+    # Remove any existing package directory and zip file
+    rm -rf "${PACKAGE_DIR}"
+    rm -f "${ZIPNAME}"
+
+    # Create the package directory
+    mkdir -p "${PACKAGE_DIR}"
+
+    # Use rsync to copy files, excluding those in .distignore
+    log "Copying files to package directory..."
+    rsync -av --exclude-from='.distignore' ./ "${PACKAGE_DIR}/"
+
+    # Create the zip file from the package directory
+    log "Creating zip file..."
+    cd "${PACKAGE_DIR}"
+    zip -r "../${ZIPNAME}" .
+    cd ..
+
+    # Clean up the package directory
+    log "Cleaning up..."
+    rm -rf "${PACKAGE_DIR}"
+
+    log "Zip file '${ZIPNAME}' created successfully."
+}
+
+# Main script execution
+main() {
+    log "Starting build process..."
+
+    install_jq
+    install_perl
+
+    VERSION=$(get_version)
+    log "Extracted version: ${VERSION}"
+
+    build_plugin
+    update_version_header "${VERSION}"
+    update_define_constant "${VERSION}"
+    create_zip "${VERSION}"
+
+    log "Build process completed successfully."
+}
+
+# Execute the main function
+main
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b5b8706
--- /dev/null
+++ b/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "bobgo-magento-plugin",
+  "description": "Bob Go magento plugin",
+  "version": "1.0.34",
+  "license": "GPL-2.0-or-later",
+  "scripts": {
+    "prepare": "husky install",
+    "update-version-files": "node update-version.js"
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "npm config set git-tag-version false && npm version patch && npm run update-version-files && git add package.json etc/module.xml composer.json && pretty-quick --staged"
+    }
+  },
+  "devDependencies": {
+    "husky": "^8.0.1",
+    "npm-run-all": "^4.1.5"
+  }
+}
diff --git a/update-version.js b/update-version.js
new file mode 100644
index 0000000..f5a9606
--- /dev/null
+++ b/update-version.js
@@ -0,0 +1,36 @@
+const fs = require('fs');
+
+// Read version from package.json
+const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
+const version = packageJson.version;
+
+// Files to update
+const filesToUpdate = ['composer.json', 'etc/module.xml'];
+
+// Function to update version in files
+function updateVersionInFile(filePath) {
+  let content = fs.readFileSync(filePath, 'utf8');
+
+  if (filePath === 'composer.json') {
+    // Update the Version header in the plugin file
+    // Update the version in composer.json
+    content = content.replace(
+        /(\"version\":\s*\")([0-9.]+)(\"\,)/g,
+        `$1${version}$3`
+    );
+  }
+
+  if (filePath === 'etc/module.xml') {
+    // Update the version tag in etc/module.xml
+    content = content.replace(
+      /(setup_version=")([^"]*)/g,
+      `$1${version}`
+    );
+
+  }
+
+  fs.writeFileSync(filePath, content);
+}
+
+// Update each file
+filesToUpdate.forEach(updateVersionInFile);
-- 
GitLab


From 7e4c1824dd6fe0e3b0088c9debed73795cf361b7 Mon Sep 17 00:00:00 2001
From: Arno Rossouw <arno@bob.co.za>
Date: Mon, 4 Nov 2024 09:47:22 +0200
Subject: [PATCH 43/56] 7-INFRASTRUCTURE :: exclude package dir from
 make-zip.sh

---
 .distignore    | 1 +
 composer.json  | 2 +-
 etc/module.xml | 2 +-
 package.json   | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/.distignore b/.distignore
index e5dc85b..e06a047 100644
--- a/.distignore
+++ b/.distignore
@@ -9,3 +9,4 @@ make-zip.sh
 update-version.js
 .gitlab-ci.yml
 .gitignore
+package
diff --git a/composer.json b/composer.json
index 07aad65..7962a85 100644
--- a/composer.json
+++ b/composer.json
@@ -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.34",
+    "version": "1.0.36",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/module.xml b/etc/module.xml
index d94e8d2..6a1ae04 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.34">
+    <module name="BobGroup_BobGo" setup_version="1.0.36">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package.json b/package.json
index b5b8706..91a85bc 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.34",
+  "version": "1.0.36",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab


From b023bc7ee3e5b2c619cc7f72d14a181128d5e44e Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 11 Nov 2024 14:00:48 +0200
Subject: [PATCH 44/56] hide tracking page

---
 etc/adminhtml/system.xml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 16f3d83..1d01da5 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -44,7 +44,9 @@
                         <field id="enable_webhooks">1</field>
                     </depends>
                 </field>
-                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
+<!--                Hiding the `Enable Track My Order` setting for now-->
+<!--                To show the setting again `showInDefault="1" showInWebsite="1" showInStore="1"` -->
+                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">
                     <label>Enable Track My Order</label>
                     <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
-- 
GitLab


From 0869b518d710ff483655d977e205949bad1ab43f Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 11 Nov 2024 14:11:24 +0200
Subject: [PATCH 45/56] hide tracking page

---
 etc/adminhtml/system.xml | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 1d01da5..c08fe4d 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -45,12 +45,11 @@
                     </depends>
                 </field>
 <!--                Hiding the `Enable Track My Order` setting for now-->
-<!--                To show the setting again `showInDefault="1" showInWebsite="1" showInStore="1"` -->
-                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">
-                    <label>Enable Track My Order</label>
-                    <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
-                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
-                </field>
+<!--                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">-->
+<!--                    <label>Enable Track My Order</label>-->
+<!--                    <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>-->
+<!--                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>-->
+<!--                </field>-->
             </group>
         </section>
     </system>
-- 
GitLab


From ce4c61daf52a1652ad2ba3d6dff84c1153d1a683 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Mon, 11 Nov 2024 15:43:45 +0200
Subject: [PATCH 46/56] hide tracking page

---
 etc/adminhtml/system.xml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index c08fe4d..81e9649 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -45,11 +45,11 @@
                     </depends>
                 </field>
 <!--                Hiding the `Enable Track My Order` setting for now-->
-<!--                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">-->
-<!--                    <label>Enable Track My Order</label>-->
-<!--                    <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>-->
-<!--                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>-->
-<!--                </field>-->
+                <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">
+                    <label>Enable Track My Order</label>
+                    <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
+                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
+                </field>
             </group>
         </section>
     </system>
-- 
GitLab


From a092e7cc9bfb79d94f27535a560a9be37991ab59 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Tue, 12 Nov 2024 12:28:03 +0200
Subject: [PATCH 47/56] add check for empty webhook key

---
 Model/Carrier/BobGo.php       | 5 +++++
 Observer/OrderWebhookBase.php | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 1260bbf..d269be1 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -1066,6 +1066,11 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
             \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();
 
diff --git a/Observer/OrderWebhookBase.php b/Observer/OrderWebhookBase.php
index 62988c4..311daa7 100644
--- a/Observer/OrderWebhookBase.php
+++ b/Observer/OrderWebhookBase.php
@@ -52,6 +52,11 @@ abstract class OrderWebhookBase implements ObserverInterface
 
         // 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);
     }
-- 
GitLab


From e08d0c00f4e1a1c063a5876f856902bb47de154c Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Wed, 2 Apr 2025 11:58:31 +0200
Subject: [PATCH 48/56] #19 - prevent null values for allowed methods

---
 Model/Carrier/BobGo.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index d269be1..938e847 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -535,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 ($allowedMethods === false || $allowedMethods === null || trim($allowedMethods) === '') {
             return []; // Return an empty array if no allowed methods are configured
         }
 
-- 
GitLab


From 9a2c1137a6dde6ed5d3c2369017a375a1b3ad156 Mon Sep 17 00:00:00 2001
From: "@ChristelLoftus" <christel@bob.co.za>
Date: Fri, 4 Apr 2025 07:52:45 +0200
Subject: [PATCH 49/56] #19 - use if empty instead to cater for all 3 checks

---
 Model/Carrier/BobGo.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Model/Carrier/BobGo.php b/Model/Carrier/BobGo.php
index 938e847..12e46e6 100644
--- a/Model/Carrier/BobGo.php
+++ b/Model/Carrier/BobGo.php
@@ -535,7 +535,7 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
     public function getAllowedMethods(): array
     {
         $allowedMethods = $this->getConfigData('allowed_methods');
-        if ($allowedMethods === false || $allowedMethods === null || trim($allowedMethods) === '') {
+        if (empty($allowedMethods)) {
             return []; // Return an empty array if no allowed methods are configured
         }
 
-- 
GitLab


From 88aeeb20fcb64b6085bd6117bc94ebdbb64450ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 09:48:19 +0200
Subject: [PATCH 50/56] ADHOC :: Wording changes

---
 etc/adminhtml/system.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 81e9649..5850116 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -33,13 +33,13 @@
                 <field id="enable_webhooks" translate="label" type="select" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Enable webhooks</label>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
-                    <comment>Enable or disable the webhook functionality for Bob Go.</comment>
+                    <comment>When enabled, webhooks will be sent to Bob Go to notify about order creation and updates, ensuring real-time synchronization between your store and Bob Go.</comment>
                 </field>
 
                 <!-- Webhook Key Input Field -->
                 <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
-                    <label>Webhook key</label>
-                    <comment>Enter Bob Go integration consumer secret key for webhook authentication.</comment>
+                    <label>Webhook authentication key</label>
+                    <comment>Enter your Bob Go integration API consumer secret key for webhook authentication.</comment>
                     <depends>
                         <field id="enable_webhooks">1</field>
                     </depends>
-- 
GitLab


From 97ef02f79c41dec35036e414bc7ba766d45c001b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:08:13 +0200
Subject: [PATCH 51/56] ADHOC :: Remove check to only show webhook key if
 webhooks are enabled

---
 .gitignore               | 2 ++
 etc/adminhtml/system.xml | 3 ---
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore
index 918863b..6450684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
 node_modules
 *.zip
+.idea
+/.idea/
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 5850116..1b718c6 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -40,9 +40,6 @@
                 <field id="webhook_key" translate="label" type="text" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Webhook authentication key</label>
                     <comment>Enter your Bob Go integration API consumer secret key for webhook authentication.</comment>
-                    <depends>
-                        <field id="enable_webhooks">1</field>
-                    </depends>
                 </field>
 <!--                Hiding the `Enable Track My Order` setting for now-->
                 <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">
-- 
GitLab


From 66b4162c5e284c2714b80489892e4cef74879403 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:11:50 +0200
Subject: [PATCH 52/56] ADHOC :: Wording change

---
 composer.json            |    2 +-
 etc/adminhtml/system.xml |    4 +-
 etc/module.xml           |    2 +-
 package-lock.json        | 1901 ++++++++++++++++++++++++++++++++++++++
 package.json             |    2 +-
 5 files changed, 1906 insertions(+), 5 deletions(-)
 create mode 100644 package-lock.json

diff --git a/composer.json b/composer.json
index 7962a85..af2ae11 100644
--- a/composer.json
+++ b/composer.json
@@ -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.36",
+    "version": "1.0.37",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 1b718c6..a834ac2 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -20,7 +20,7 @@
                 </field>
                 <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Enable Bob Go rates at checkout</label>
-                    <comment>When this setting is enabled, your customers will be presented with shipping rates at checkout, as configured on the Bob Go platform under Rates at checkout.</comment>
+                    <comment>When enabled, your customers will be presented with shipping rates at checkout, as configured on the Bob Go platform under Rates at checkout.</comment>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                 </field>
                 <field id="additional_info" translate="label" type="select" sortOrder="7" showInDefault="1" showInWebsite="1">
@@ -43,7 +43,7 @@
                 </field>
 <!--                Hiding the `Enable Track My Order` setting for now-->
                 <field id="enable_track_order" translate="label" type="select" sortOrder="10" showInDefault="0" showInWebsite="0" showInStore="0">
-                    <label>Enable Track My Order</label>
+                    <label>Enable Track my order</label>
                     <comment>When this setting is enabled, your customers will be presented with a page to track orders.</comment>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                 </field>
diff --git a/etc/module.xml b/etc/module.xml
index 6a1ae04..d49e765 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.36">
+    <module name="BobGroup_BobGo" setup_version="1.0.37">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..a908a08
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1901 @@
+{
+  "name": "bobgo-magento-plugin",
+  "version": "1.0.37",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "bobgo-magento-plugin",
+      "version": "1.0.37",
+      "license": "GPL-2.0-or-later",
+      "devDependencies": {
+        "husky": "^8.0.1",
+        "npm-run-all": "^4.1.5"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/array-buffer-byte-length": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+      "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "is-array-buffer": "^3.0.5"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/arraybuffer.prototype.slice": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+      "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.1",
+        "call-bind": "^1.0.8",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.5",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "is-array-buffer": "^3.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/async-function": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+      "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/available-typed-arrays": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+      "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+      "dev": true,
+      "dependencies": {
+        "possible-typed-array-names": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+      "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+      "dev": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.0",
+        "es-define-property": "^1.0.0",
+        "get-intrinsic": "^1.2.4",
+        "set-function-length": "^1.2.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/call-bound": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true
+    },
+    "node_modules/cross-spawn": {
+      "version": "6.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
+      "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
+      "dev": true,
+      "dependencies": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      },
+      "engines": {
+        "node": ">=4.8"
+      }
+    },
+    "node_modules/data-view-buffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+      "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/data-view-byte-length": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+      "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/inspect-js"
+      }
+    },
+    "node_modules/data-view-byte-offset": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+      "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/define-data-property": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+      "dev": true,
+      "dependencies": {
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/define-properties": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+      "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "has-property-descriptors": "^1.0.0",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "dev": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "dependencies": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "node_modules/es-abstract": {
+      "version": "1.23.9",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
+      "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.2",
+        "arraybuffer.prototype.slice": "^1.0.4",
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.3",
+        "data-view-buffer": "^1.0.2",
+        "data-view-byte-length": "^1.0.2",
+        "data-view-byte-offset": "^1.0.1",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.0.0",
+        "es-set-tostringtag": "^2.1.0",
+        "es-to-primitive": "^1.3.0",
+        "function.prototype.name": "^1.1.8",
+        "get-intrinsic": "^1.2.7",
+        "get-proto": "^1.0.0",
+        "get-symbol-description": "^1.1.0",
+        "globalthis": "^1.0.4",
+        "gopd": "^1.2.0",
+        "has-property-descriptors": "^1.0.2",
+        "has-proto": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "internal-slot": "^1.1.0",
+        "is-array-buffer": "^3.0.5",
+        "is-callable": "^1.2.7",
+        "is-data-view": "^1.0.2",
+        "is-regex": "^1.2.1",
+        "is-shared-array-buffer": "^1.0.4",
+        "is-string": "^1.1.1",
+        "is-typed-array": "^1.1.15",
+        "is-weakref": "^1.1.0",
+        "math-intrinsics": "^1.1.0",
+        "object-inspect": "^1.13.3",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.7",
+        "own-keys": "^1.0.1",
+        "regexp.prototype.flags": "^1.5.3",
+        "safe-array-concat": "^1.1.3",
+        "safe-push-apply": "^1.0.0",
+        "safe-regex-test": "^1.1.0",
+        "set-proto": "^1.0.0",
+        "string.prototype.trim": "^1.2.10",
+        "string.prototype.trimend": "^1.0.9",
+        "string.prototype.trimstart": "^1.0.8",
+        "typed-array-buffer": "^1.0.3",
+        "typed-array-byte-length": "^1.0.3",
+        "typed-array-byte-offset": "^1.0.4",
+        "typed-array-length": "^1.0.7",
+        "unbox-primitive": "^1.1.0",
+        "which-typed-array": "^1.1.18"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-to-primitive": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+      "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.2.7",
+        "is-date-object": "^1.0.5",
+        "is-symbol": "^1.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/for-each": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.2.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/function.prototype.name": {
+      "version": "1.1.8",
+      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+      "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.3",
+        "define-properties": "^1.2.1",
+        "functions-have-names": "^1.2.3",
+        "hasown": "^2.0.2",
+        "is-callable": "^1.2.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/functions-have-names": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "dev": true,
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/get-symbol-description": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+      "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/globalthis": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+      "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.2.1",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "dev": true
+    },
+    "node_modules/has-bigints": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+      "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has-property-descriptors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+      "dev": true,
+      "dependencies": {
+        "es-define-property": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-proto": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+      "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+      "dev": true,
+      "dependencies": {
+        "dunder-proto": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hosted-git-info": {
+      "version": "2.8.9",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+      "dev": true
+    },
+    "node_modules/husky": {
+      "version": "8.0.3",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
+      "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+      "dev": true,
+      "bin": {
+        "husky": "lib/bin.js"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/typicode"
+      }
+    },
+    "node_modules/internal-slot": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+      "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "hasown": "^2.0.2",
+        "side-channel": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/is-array-buffer": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+      "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.3",
+        "get-intrinsic": "^1.2.6"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "dev": true
+    },
+    "node_modules/is-async-function": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+      "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+      "dev": true,
+      "dependencies": {
+        "async-function": "^1.0.0",
+        "call-bound": "^1.0.3",
+        "get-proto": "^1.0.1",
+        "has-tostringtag": "^1.0.2",
+        "safe-regex-test": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-bigint": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+      "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+      "dev": true,
+      "dependencies": {
+        "has-bigints": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-boolean-object": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+      "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-callable": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "dev": true,
+      "dependencies": {
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-data-view": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+      "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "get-intrinsic": "^1.2.6",
+        "is-typed-array": "^1.1.13"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-date-object": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+      "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-finalizationregistry": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+      "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-generator-function": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
+      "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "get-proto": "^1.0.0",
+        "has-tostringtag": "^1.0.2",
+        "safe-regex-test": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-map": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+      "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-number-object": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+      "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-regex": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+      "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "gopd": "^1.2.0",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-set": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+      "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-shared-array-buffer": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+      "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-string": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+      "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-symbol": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+      "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "has-symbols": "^1.1.0",
+        "safe-regex-test": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-typed-array": {
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+      "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+      "dev": true,
+      "dependencies": {
+        "which-typed-array": "^1.1.16"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakmap": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+      "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakref": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+      "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakset": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+      "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "get-intrinsic": "^1.2.6"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "node_modules/json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "node_modules/load-json-file": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/memorystream": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+      "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "node_modules/normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "dependencies": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "node_modules/npm-run-all": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+      "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "chalk": "^2.4.1",
+        "cross-spawn": "^6.0.5",
+        "memorystream": "^0.3.1",
+        "minimatch": "^3.0.4",
+        "pidtree": "^0.3.0",
+        "read-pkg": "^3.0.0",
+        "shell-quote": "^1.6.1",
+        "string.prototype.padend": "^3.0.0"
+      },
+      "bin": {
+        "npm-run-all": "bin/npm-run-all/index.js",
+        "run-p": "bin/run-p/index.js",
+        "run-s": "bin/run-s/index.js"
+      },
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.4",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/object.assign": {
+      "version": "4.1.7",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+      "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.3",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0",
+        "has-symbols": "^1.1.0",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/own-keys": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+      "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.6",
+        "object-keys": "^1.1.1",
+        "safe-push-apply": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+      "dev": true,
+      "dependencies": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/path-type": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+      "dev": true,
+      "dependencies": {
+        "pify": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/pidtree": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+      "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+      "dev": true,
+      "bin": {
+        "pidtree": "bin/pidtree.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/possible-typed-array-names": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+      "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/read-pkg": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+      "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+      "dev": true,
+      "dependencies": {
+        "load-json-file": "^4.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/reflect.getprototypeof": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+      "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.9",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.0.0",
+        "get-intrinsic": "^1.2.7",
+        "get-proto": "^1.0.1",
+        "which-builtin-type": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/regexp.prototype.flags": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+      "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "define-properties": "^1.2.1",
+        "es-errors": "^1.3.0",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "set-function-name": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.10",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.16.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safe-array-concat": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+      "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.2",
+        "get-intrinsic": "^1.2.6",
+        "has-symbols": "^1.1.0",
+        "isarray": "^2.0.5"
+      },
+      "engines": {
+        "node": ">=0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safe-push-apply": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+      "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "isarray": "^2.0.5"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safe-regex-test": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+      "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "is-regex": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/set-function-length": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.1.4",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/set-function-name": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+      "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.1.4",
+        "es-errors": "^1.3.0",
+        "functions-have-names": "^1.2.3",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/set-proto": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+      "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+      "dev": true,
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/shell-quote": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
+      "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3",
+        "side-channel-list": "^1.0.0",
+        "side-channel-map": "^1.0.1",
+        "side-channel-weakmap": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-list": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+      "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-weakmap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3",
+        "side-channel-map": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/spdx-correct": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+      "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+      "dev": true,
+      "dependencies": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "node_modules/spdx-exceptions": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+      "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+      "dev": true
+    },
+    "node_modules/spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dev": true,
+      "dependencies": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "node_modules/spdx-license-ids": {
+      "version": "3.0.21",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz",
+      "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
+      "dev": true
+    },
+    "node_modules/string.prototype.padend": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
+      "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.2",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trim": {
+      "version": "1.2.10",
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+      "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.2",
+        "define-data-property": "^1.1.4",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.5",
+        "es-object-atoms": "^1.0.0",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimend": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+      "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.2",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimstart": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+      "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-buffer": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+      "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "is-typed-array": "^1.1.14"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/typed-array-byte-length": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+      "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.8",
+        "for-each": "^0.3.3",
+        "gopd": "^1.2.0",
+        "has-proto": "^1.2.0",
+        "is-typed-array": "^1.1.14"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-byte-offset": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+      "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.8",
+        "for-each": "^0.3.3",
+        "gopd": "^1.2.0",
+        "has-proto": "^1.2.0",
+        "is-typed-array": "^1.1.15",
+        "reflect.getprototypeof": "^1.0.9"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-length": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+      "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "for-each": "^0.3.3",
+        "gopd": "^1.0.1",
+        "is-typed-array": "^1.1.13",
+        "possible-typed-array-names": "^1.0.0",
+        "reflect.getprototypeof": "^1.0.6"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/unbox-primitive": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+      "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "has-bigints": "^1.0.2",
+        "has-symbols": "^1.1.0",
+        "which-boxed-primitive": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "dependencies": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "which": "bin/which"
+      }
+    },
+    "node_modules/which-boxed-primitive": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+      "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+      "dev": true,
+      "dependencies": {
+        "is-bigint": "^1.1.0",
+        "is-boolean-object": "^1.2.1",
+        "is-number-object": "^1.1.1",
+        "is-string": "^1.1.1",
+        "is-symbol": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-builtin-type": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+      "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "function.prototype.name": "^1.1.6",
+        "has-tostringtag": "^1.0.2",
+        "is-async-function": "^2.0.0",
+        "is-date-object": "^1.1.0",
+        "is-finalizationregistry": "^1.1.0",
+        "is-generator-function": "^1.0.10",
+        "is-regex": "^1.2.1",
+        "is-weakref": "^1.0.2",
+        "isarray": "^2.0.5",
+        "which-boxed-primitive": "^1.1.0",
+        "which-collection": "^1.0.2",
+        "which-typed-array": "^1.1.16"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-collection": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+      "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+      "dev": true,
+      "dependencies": {
+        "is-map": "^2.0.3",
+        "is-set": "^2.0.3",
+        "is-weakmap": "^2.0.2",
+        "is-weakset": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-typed-array": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+      "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.4",
+        "for-each": "^0.3.5",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
index 91a85bc..bb53460 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.36",
+  "version": "1.0.37",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab


From 127b8912786df897b96bdd5770b0961eb1792db9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:12:17 +0200
Subject: [PATCH 53/56] ADHOC :: Wording change

---
 composer.json            | 2 +-
 etc/adminhtml/system.xml | 2 +-
 etc/module.xml           | 2 +-
 package.json             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/composer.json b/composer.json
index af2ae11..59cf095 100644
--- a/composer.json
+++ b/composer.json
@@ -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.37",
+    "version": "1.0.38",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index a834ac2..03d7787 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -33,7 +33,7 @@
                 <field id="enable_webhooks" translate="label" type="select" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Enable webhooks</label>
                     <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
-                    <comment>When enabled, webhooks will be sent to Bob Go to notify about order creation and updates, ensuring real-time synchronization between your store and Bob Go.</comment>
+                    <comment>When this setting is enabled, webhooks will be sent to Bob Go to notify about order creation and updates, ensuring real-time synchronization between your store and Bob Go.</comment>
                 </field>
 
                 <!-- Webhook Key Input Field -->
diff --git a/etc/module.xml b/etc/module.xml
index d49e765..b6cd413 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.37">
+    <module name="BobGroup_BobGo" setup_version="1.0.38">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package.json b/package.json
index bb53460..0b6984b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.37",
+  "version": "1.0.38",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab


From 7747491f52596730b8ca8e58c53c916bec00e517 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:12:25 +0200
Subject: [PATCH 54/56] ADHOC :: Wording change

---
 composer.json     | 2 +-
 etc/module.xml    | 2 +-
 package-lock.json | 4 ++--
 package.json      | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/composer.json b/composer.json
index 59cf095..01abbbf 100644
--- a/composer.json
+++ b/composer.json
@@ -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.38",
+    "version": "1.0.39",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/module.xml b/etc/module.xml
index b6cd413..81828e8 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.38">
+    <module name="BobGroup_BobGo" setup_version="1.0.39">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package-lock.json b/package-lock.json
index a908a08..f622b48 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "bobgo-magento-plugin",
-  "version": "1.0.37",
+  "version": "1.0.38",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "bobgo-magento-plugin",
-      "version": "1.0.37",
+      "version": "1.0.38",
       "license": "GPL-2.0-or-later",
       "devDependencies": {
         "husky": "^8.0.1",
diff --git a/package.json b/package.json
index 0b6984b..50a44a9 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.38",
+  "version": "1.0.39",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab


From 6eb8f023e15ce9f2cd09b3c36cbf5e95db56cb90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:13:29 +0200
Subject: [PATCH 55/56] ADHOC :: Remove package lock

---
 composer.json     |    2 +-
 etc/module.xml    |    2 +-
 package-lock.json | 1901 ---------------------------------------------
 package.json      |    2 +-
 4 files changed, 3 insertions(+), 1904 deletions(-)
 delete mode 100644 package-lock.json

diff --git a/composer.json b/composer.json
index 01abbbf..9b2166f 100644
--- a/composer.json
+++ b/composer.json
@@ -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.39",
+    "version": "1.0.40",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/module.xml b/etc/module.xml
index 81828e8..962488e 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.39">
+    <module name="BobGroup_BobGo" setup_version="1.0.40">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index f622b48..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,1901 +0,0 @@
-{
-  "name": "bobgo-magento-plugin",
-  "version": "1.0.38",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "bobgo-magento-plugin",
-      "version": "1.0.38",
-      "license": "GPL-2.0-or-later",
-      "devDependencies": {
-        "husky": "^8.0.1",
-        "npm-run-all": "^4.1.5"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/array-buffer-byte-length": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
-      "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "is-array-buffer": "^3.0.5"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/arraybuffer.prototype.slice": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
-      "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
-      "dev": true,
-      "dependencies": {
-        "array-buffer-byte-length": "^1.0.1",
-        "call-bind": "^1.0.8",
-        "define-properties": "^1.2.1",
-        "es-abstract": "^1.23.5",
-        "es-errors": "^1.3.0",
-        "get-intrinsic": "^1.2.6",
-        "is-array-buffer": "^3.0.4"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/async-function": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
-      "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/available-typed-arrays": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
-      "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
-      "dev": true,
-      "dependencies": {
-        "possible-typed-array-names": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "dev": true
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/call-bind": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
-      "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
-      "dev": true,
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.0",
-        "es-define-property": "^1.0.0",
-        "get-intrinsic": "^1.2.4",
-        "set-function-length": "^1.2.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/call-bind-apply-helpers": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
-      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/call-bound": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
-      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
-      "dev": true,
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.2",
-        "get-intrinsic": "^1.3.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
-    },
-    "node_modules/cross-spawn": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
-      "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
-      "dev": true,
-      "dependencies": {
-        "nice-try": "^1.0.4",
-        "path-key": "^2.0.1",
-        "semver": "^5.5.0",
-        "shebang-command": "^1.2.0",
-        "which": "^1.2.9"
-      },
-      "engines": {
-        "node": ">=4.8"
-      }
-    },
-    "node_modules/data-view-buffer": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
-      "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "es-errors": "^1.3.0",
-        "is-data-view": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/data-view-byte-length": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
-      "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "es-errors": "^1.3.0",
-        "is-data-view": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/inspect-js"
-      }
-    },
-    "node_modules/data-view-byte-offset": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
-      "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "es-errors": "^1.3.0",
-        "is-data-view": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/define-data-property": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
-      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
-      "dev": true,
-      "dependencies": {
-        "es-define-property": "^1.0.0",
-        "es-errors": "^1.3.0",
-        "gopd": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/define-properties": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
-      "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
-      "dev": true,
-      "dependencies": {
-        "define-data-property": "^1.0.1",
-        "has-property-descriptors": "^1.0.0",
-        "object-keys": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/dunder-proto": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
-      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
-      "dev": true,
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "gopd": "^1.2.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-      "dev": true,
-      "dependencies": {
-        "is-arrayish": "^0.2.1"
-      }
-    },
-    "node_modules/es-abstract": {
-      "version": "1.23.9",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
-      "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
-      "dev": true,
-      "dependencies": {
-        "array-buffer-byte-length": "^1.0.2",
-        "arraybuffer.prototype.slice": "^1.0.4",
-        "available-typed-arrays": "^1.0.7",
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.3",
-        "data-view-buffer": "^1.0.2",
-        "data-view-byte-length": "^1.0.2",
-        "data-view-byte-offset": "^1.0.1",
-        "es-define-property": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.0.0",
-        "es-set-tostringtag": "^2.1.0",
-        "es-to-primitive": "^1.3.0",
-        "function.prototype.name": "^1.1.8",
-        "get-intrinsic": "^1.2.7",
-        "get-proto": "^1.0.0",
-        "get-symbol-description": "^1.1.0",
-        "globalthis": "^1.0.4",
-        "gopd": "^1.2.0",
-        "has-property-descriptors": "^1.0.2",
-        "has-proto": "^1.2.0",
-        "has-symbols": "^1.1.0",
-        "hasown": "^2.0.2",
-        "internal-slot": "^1.1.0",
-        "is-array-buffer": "^3.0.5",
-        "is-callable": "^1.2.7",
-        "is-data-view": "^1.0.2",
-        "is-regex": "^1.2.1",
-        "is-shared-array-buffer": "^1.0.4",
-        "is-string": "^1.1.1",
-        "is-typed-array": "^1.1.15",
-        "is-weakref": "^1.1.0",
-        "math-intrinsics": "^1.1.0",
-        "object-inspect": "^1.13.3",
-        "object-keys": "^1.1.1",
-        "object.assign": "^4.1.7",
-        "own-keys": "^1.0.1",
-        "regexp.prototype.flags": "^1.5.3",
-        "safe-array-concat": "^1.1.3",
-        "safe-push-apply": "^1.0.0",
-        "safe-regex-test": "^1.1.0",
-        "set-proto": "^1.0.0",
-        "string.prototype.trim": "^1.2.10",
-        "string.prototype.trimend": "^1.0.9",
-        "string.prototype.trimstart": "^1.0.8",
-        "typed-array-buffer": "^1.0.3",
-        "typed-array-byte-length": "^1.0.3",
-        "typed-array-byte-offset": "^1.0.4",
-        "typed-array-length": "^1.0.7",
-        "unbox-primitive": "^1.1.0",
-        "which-typed-array": "^1.1.18"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/es-define-property": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
-      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-errors": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
-      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-object-atoms": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
-      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-set-tostringtag": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
-      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "get-intrinsic": "^1.2.6",
-        "has-tostringtag": "^1.0.2",
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-to-primitive": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
-      "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
-      "dev": true,
-      "dependencies": {
-        "is-callable": "^1.2.7",
-        "is-date-object": "^1.0.5",
-        "is-symbol": "^1.0.4"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/for-each": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
-      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
-      "dev": true,
-      "dependencies": {
-        "is-callable": "^1.2.7"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/function-bind": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/function.prototype.name": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
-      "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.3",
-        "define-properties": "^1.2.1",
-        "functions-have-names": "^1.2.3",
-        "hasown": "^2.0.2",
-        "is-callable": "^1.2.7"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/functions-have-names": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
-      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-intrinsic": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
-      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.2",
-        "es-define-property": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.1.1",
-        "function-bind": "^1.1.2",
-        "get-proto": "^1.0.1",
-        "gopd": "^1.2.0",
-        "has-symbols": "^1.1.0",
-        "hasown": "^2.0.2",
-        "math-intrinsics": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-proto": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
-      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
-      "dev": true,
-      "dependencies": {
-        "dunder-proto": "^1.0.1",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/get-symbol-description": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
-      "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "es-errors": "^1.3.0",
-        "get-intrinsic": "^1.2.6"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/globalthis": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
-      "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
-      "dev": true,
-      "dependencies": {
-        "define-properties": "^1.2.1",
-        "gopd": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/gopd": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
-      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/graceful-fs": {
-      "version": "4.2.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
-      "dev": true
-    },
-    "node_modules/has-bigints": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
-      "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/has-property-descriptors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
-      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
-      "dev": true,
-      "dependencies": {
-        "es-define-property": "^1.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-proto": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
-      "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
-      "dev": true,
-      "dependencies": {
-        "dunder-proto": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-symbols": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
-      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-tostringtag": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
-      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
-      "dev": true,
-      "dependencies": {
-        "has-symbols": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/hasown": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-      "dev": true,
-      "dependencies": {
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/hosted-git-info": {
-      "version": "2.8.9",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
-      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
-      "dev": true
-    },
-    "node_modules/husky": {
-      "version": "8.0.3",
-      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
-      "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
-      "dev": true,
-      "bin": {
-        "husky": "lib/bin.js"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/typicode"
-      }
-    },
-    "node_modules/internal-slot": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
-      "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "hasown": "^2.0.2",
-        "side-channel": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/is-array-buffer": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
-      "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.3",
-        "get-intrinsic": "^1.2.6"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-arrayish": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
-      "dev": true
-    },
-    "node_modules/is-async-function": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
-      "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
-      "dev": true,
-      "dependencies": {
-        "async-function": "^1.0.0",
-        "call-bound": "^1.0.3",
-        "get-proto": "^1.0.1",
-        "has-tostringtag": "^1.0.2",
-        "safe-regex-test": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-bigint": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
-      "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
-      "dev": true,
-      "dependencies": {
-        "has-bigints": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-boolean-object": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
-      "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-callable": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
-      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-core-module": {
-      "version": "2.16.1",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
-      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
-      "dev": true,
-      "dependencies": {
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-data-view": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
-      "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "get-intrinsic": "^1.2.6",
-        "is-typed-array": "^1.1.13"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-date-object": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
-      "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-finalizationregistry": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
-      "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-generator-function": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
-      "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "get-proto": "^1.0.0",
-        "has-tostringtag": "^1.0.2",
-        "safe-regex-test": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-map": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
-      "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-number-object": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
-      "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-regex": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
-      "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "gopd": "^1.2.0",
-        "has-tostringtag": "^1.0.2",
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-set": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
-      "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-shared-array-buffer": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
-      "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-string": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
-      "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-symbol": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
-      "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "has-symbols": "^1.1.0",
-        "safe-regex-test": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-typed-array": {
-      "version": "1.1.15",
-      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
-      "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
-      "dev": true,
-      "dependencies": {
-        "which-typed-array": "^1.1.16"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-weakmap": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
-      "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-weakref": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
-      "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-weakset": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
-      "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "get-intrinsic": "^1.2.6"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/isarray": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
-      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
-      "dev": true
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "dev": true
-    },
-    "node_modules/json-parse-better-errors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
-      "dev": true
-    },
-    "node_modules/load-json-file": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
-      "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.1.2",
-        "parse-json": "^4.0.0",
-        "pify": "^3.0.0",
-        "strip-bom": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/math-intrinsics": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
-      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/memorystream": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-      "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-      "dev": true
-    },
-    "node_modules/normalize-package-data": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
-      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
-      "dev": true,
-      "dependencies": {
-        "hosted-git-info": "^2.1.4",
-        "resolve": "^1.10.0",
-        "semver": "2 || 3 || 4 || 5",
-        "validate-npm-package-license": "^3.0.1"
-      }
-    },
-    "node_modules/npm-run-all": {
-      "version": "4.1.5",
-      "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
-      "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "chalk": "^2.4.1",
-        "cross-spawn": "^6.0.5",
-        "memorystream": "^0.3.1",
-        "minimatch": "^3.0.4",
-        "pidtree": "^0.3.0",
-        "read-pkg": "^3.0.0",
-        "shell-quote": "^1.6.1",
-        "string.prototype.padend": "^3.0.0"
-      },
-      "bin": {
-        "npm-run-all": "bin/npm-run-all/index.js",
-        "run-p": "bin/run-p/index.js",
-        "run-s": "bin/run-s/index.js"
-      },
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/object-inspect": {
-      "version": "1.13.4",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
-      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/object-keys": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/object.assign": {
-      "version": "4.1.7",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
-      "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.3",
-        "define-properties": "^1.2.1",
-        "es-object-atoms": "^1.0.0",
-        "has-symbols": "^1.1.0",
-        "object-keys": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/own-keys": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
-      "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
-      "dev": true,
-      "dependencies": {
-        "get-intrinsic": "^1.2.6",
-        "object-keys": "^1.1.1",
-        "safe-push-apply": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/parse-json": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
-      "dev": true,
-      "dependencies": {
-        "error-ex": "^1.3.1",
-        "json-parse-better-errors": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "dev": true
-    },
-    "node_modules/path-type": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-      "dev": true,
-      "dependencies": {
-        "pify": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/pidtree": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
-      "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
-      "dev": true,
-      "bin": {
-        "pidtree": "bin/pidtree.js"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/pify": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/possible-typed-array-names": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
-      "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/read-pkg": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
-      "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
-      "dev": true,
-      "dependencies": {
-        "load-json-file": "^4.0.0",
-        "normalize-package-data": "^2.3.2",
-        "path-type": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/reflect.getprototypeof": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
-      "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "define-properties": "^1.2.1",
-        "es-abstract": "^1.23.9",
-        "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.0.0",
-        "get-intrinsic": "^1.2.7",
-        "get-proto": "^1.0.1",
-        "which-builtin-type": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/regexp.prototype.flags": {
-      "version": "1.5.4",
-      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
-      "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "define-properties": "^1.2.1",
-        "es-errors": "^1.3.0",
-        "get-proto": "^1.0.1",
-        "gopd": "^1.2.0",
-        "set-function-name": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/resolve": {
-      "version": "1.22.10",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
-      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
-      "dev": true,
-      "dependencies": {
-        "is-core-module": "^2.16.0",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      },
-      "bin": {
-        "resolve": "bin/resolve"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/safe-array-concat": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
-      "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.2",
-        "get-intrinsic": "^1.2.6",
-        "has-symbols": "^1.1.0",
-        "isarray": "^2.0.5"
-      },
-      "engines": {
-        "node": ">=0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/safe-push-apply": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
-      "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "isarray": "^2.0.5"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/safe-regex-test": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
-      "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "es-errors": "^1.3.0",
-        "is-regex": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/semver": {
-      "version": "5.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/set-function-length": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
-      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
-      "dev": true,
-      "dependencies": {
-        "define-data-property": "^1.1.4",
-        "es-errors": "^1.3.0",
-        "function-bind": "^1.1.2",
-        "get-intrinsic": "^1.2.4",
-        "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/set-function-name": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
-      "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
-      "dev": true,
-      "dependencies": {
-        "define-data-property": "^1.1.4",
-        "es-errors": "^1.3.0",
-        "functions-have-names": "^1.2.3",
-        "has-property-descriptors": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/set-proto": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
-      "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
-      "dev": true,
-      "dependencies": {
-        "dunder-proto": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
-      "dev": true,
-      "dependencies": {
-        "shebang-regex": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/shell-quote": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
-      "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/side-channel": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
-      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "object-inspect": "^1.13.3",
-        "side-channel-list": "^1.0.0",
-        "side-channel-map": "^1.0.1",
-        "side-channel-weakmap": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/side-channel-list": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
-      "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
-      "dev": true,
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "object-inspect": "^1.13.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/side-channel-map": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
-      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "es-errors": "^1.3.0",
-        "get-intrinsic": "^1.2.5",
-        "object-inspect": "^1.13.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/side-channel-weakmap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
-      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "es-errors": "^1.3.0",
-        "get-intrinsic": "^1.2.5",
-        "object-inspect": "^1.13.3",
-        "side-channel-map": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/spdx-correct": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
-      "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
-      "dev": true,
-      "dependencies": {
-        "spdx-expression-parse": "^3.0.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-exceptions": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
-      "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
-      "dev": true
-    },
-    "node_modules/spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
-      "dev": true,
-      "dependencies": {
-        "spdx-exceptions": "^2.1.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-license-ids": {
-      "version": "3.0.21",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz",
-      "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
-      "dev": true
-    },
-    "node_modules/string.prototype.padend": {
-      "version": "3.1.6",
-      "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
-      "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.7",
-        "define-properties": "^1.2.1",
-        "es-abstract": "^1.23.2",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/string.prototype.trim": {
-      "version": "1.2.10",
-      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
-      "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.2",
-        "define-data-property": "^1.1.4",
-        "define-properties": "^1.2.1",
-        "es-abstract": "^1.23.5",
-        "es-object-atoms": "^1.0.0",
-        "has-property-descriptors": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/string.prototype.trimend": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
-      "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.2",
-        "define-properties": "^1.2.1",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/string.prototype.trimstart": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
-      "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.7",
-        "define-properties": "^1.2.1",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/strip-bom": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/typed-array-buffer": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
-      "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "es-errors": "^1.3.0",
-        "is-typed-array": "^1.1.14"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/typed-array-byte-length": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
-      "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.8",
-        "for-each": "^0.3.3",
-        "gopd": "^1.2.0",
-        "has-proto": "^1.2.0",
-        "is-typed-array": "^1.1.14"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/typed-array-byte-offset": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
-      "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
-      "dev": true,
-      "dependencies": {
-        "available-typed-arrays": "^1.0.7",
-        "call-bind": "^1.0.8",
-        "for-each": "^0.3.3",
-        "gopd": "^1.2.0",
-        "has-proto": "^1.2.0",
-        "is-typed-array": "^1.1.15",
-        "reflect.getprototypeof": "^1.0.9"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/typed-array-length": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
-      "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.7",
-        "for-each": "^0.3.3",
-        "gopd": "^1.0.1",
-        "is-typed-array": "^1.1.13",
-        "possible-typed-array-names": "^1.0.0",
-        "reflect.getprototypeof": "^1.0.6"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/unbox-primitive": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
-      "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "has-bigints": "^1.0.2",
-        "has-symbols": "^1.1.0",
-        "which-boxed-primitive": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/validate-npm-package-license": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
-      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
-      "dev": true,
-      "dependencies": {
-        "spdx-correct": "^3.0.0",
-        "spdx-expression-parse": "^3.0.0"
-      }
-    },
-    "node_modules/which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "which": "bin/which"
-      }
-    },
-    "node_modules/which-boxed-primitive": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
-      "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
-      "dev": true,
-      "dependencies": {
-        "is-bigint": "^1.1.0",
-        "is-boolean-object": "^1.2.1",
-        "is-number-object": "^1.1.1",
-        "is-string": "^1.1.1",
-        "is-symbol": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/which-builtin-type": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
-      "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
-      "dev": true,
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "function.prototype.name": "^1.1.6",
-        "has-tostringtag": "^1.0.2",
-        "is-async-function": "^2.0.0",
-        "is-date-object": "^1.1.0",
-        "is-finalizationregistry": "^1.1.0",
-        "is-generator-function": "^1.0.10",
-        "is-regex": "^1.2.1",
-        "is-weakref": "^1.0.2",
-        "isarray": "^2.0.5",
-        "which-boxed-primitive": "^1.1.0",
-        "which-collection": "^1.0.2",
-        "which-typed-array": "^1.1.16"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/which-collection": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
-      "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
-      "dev": true,
-      "dependencies": {
-        "is-map": "^2.0.3",
-        "is-set": "^2.0.3",
-        "is-weakmap": "^2.0.2",
-        "is-weakset": "^2.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/which-typed-array": {
-      "version": "1.1.19",
-      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
-      "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
-      "dev": true,
-      "dependencies": {
-        "available-typed-arrays": "^1.0.7",
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.4",
-        "for-each": "^0.3.5",
-        "get-proto": "^1.0.1",
-        "gopd": "^1.2.0",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    }
-  }
-}
diff --git a/package.json b/package.json
index 50a44a9..0bb7580 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.39",
+  "version": "1.0.40",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab


From edfd9d93db2232c95b0ebab7348ade3479bf3d88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franc=C3=A9=20Wilke?= <francewilke@gmail.com>
Date: Wed, 23 Apr 2025 10:48:36 +0200
Subject: [PATCH 56/56] ADHOC :: Update the endpoints

---
 Model/Carrier/UData.php | 6 +++---
 composer.json           | 2 +-
 etc/module.xml          | 2 +-
 package.json            | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php
index adf83a2..bbb17dd 100644
--- a/Model/Carrier/UData.php
+++ b/Model/Carrier/UData.php
@@ -12,19 +12,19 @@ class UData
      *
      * @var string
      */
-    public const TRACKING = 'https://api.dev.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
+    public const TRACKING = 'https://api.bobgo.co.za/tracking?channel=%s&tracking_reference=%s';
 
     /**
      * Rates API Endpoint
      *
      * @var string
      */
-    public const RATES_ENDPOINT = 'https://api.dev.bobgo.co.za/rates-at-checkout/magento';
+    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.dev.bobgo.co.za/webhook/channel/magento';
+    public const WEBHOOK_URL = 'https://api.bobgo.co.za/webhook/channel/magento';
 }
diff --git a/composer.json b/composer.json
index 9b2166f..83317ac 100644
--- a/composer.json
+++ b/composer.json
@@ -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.40",
+    "version": "1.0.41",
     "authors": [
         {
             "name": "Bob Go",
diff --git a/etc/module.xml b/etc/module.xml
index 962488e..a79063f 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -7,7 +7,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
-    <module name="BobGroup_BobGo" setup_version="1.0.40">
+    <module name="BobGroup_BobGo" setup_version="1.0.41">
         <sequence>
             <module name="Magento_Webapi"/>
             <module name="Magento_Catalog"/>
diff --git a/package.json b/package.json
index 0bb7580..e44822d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "bobgo-magento-plugin",
   "description": "Bob Go magento plugin",
-  "version": "1.0.40",
+  "version": "1.0.41",
   "license": "GPL-2.0-or-later",
   "scripts": {
     "prepare": "husky install",
-- 
GitLab