From bba6a5575410aaacd2c0a4440501a9e4d3220ac8 Mon Sep 17 00:00:00 2001 From: Luca Scalzotto Date: Thu, 25 Jan 2024 10:31:36 +0100 Subject: [PATCH] Add expected delivery dates for PostNL and DHL (#20) --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 6 ++ Model/Carrier/Parcelpro.php | 164 ++++++++++++++++++++++++++++++++---- composer.json | 9 +- etc/adminhtml/system.xml | 22 ++++- install.sh | 2 +- 6 files changed, 182 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e799b4..95917ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,5 +19,6 @@ jobs: - uses: php-actions/composer@v6 with: args: --ignore-platform-reqs + php_version: 8.2 - run: composer cs:check - run: composer md diff --git a/CHANGELOG.md b/CHANGELOG.md index fcdeeca..ad1636f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 2.18.0 - 2024-01-25 + +### New + +- Optie om verwachte bezorgdatum voor PostNL en DHL weer te geven toegevoegd + ## 2.17.2 - 2024-01-18 ### Fixes diff --git a/Model/Carrier/Parcelpro.php b/Model/Carrier/Parcelpro.php index 73a954d..860d3ca 100644 --- a/Model/Carrier/Parcelpro.php +++ b/Model/Carrier/Parcelpro.php @@ -2,25 +2,24 @@ namespace Parcelpro\Shipment\Model\Carrier; +use DateInterval; +use DateTime; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Model\Rate\Result; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Parcelpro extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements \Magento\Shipping\Model\Carrier\CarrierInterface { - /** - * @var string - */ protected $_code = 'parcelpro'; - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory - * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory - * @param array $data - */ + /** @var \Magento\Framework\Locale\Resolver */ + protected $localeResolver; + + private $apiUrl = 'https://login.parcelpro.nl'; + public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory, @@ -28,11 +27,13 @@ public function __construct( \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory, \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory, \Magento\Framework\Serialize\Serializer\Json $serialize, + \Magento\Framework\Locale\Resolver $localeResolver, array $data = [] ) { $this->_rateResultFactory = $rateResultFactory; $this->_rateMethodFactory = $rateMethodFactory; $this->serialize = $serialize; + $this->localeResolver = $localeResolver; parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data); } @@ -110,11 +111,17 @@ public function collectRates(RateRequest $request) return false; } + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + + /** @var \Magento\Checkout\Model\Session $checkoutSession */ + $checkoutSession = $objectManager->create('\Magento\Checkout\Model\Session'); + $shippingAddress = $checkoutSession->getQuote()->getShippingAddress(); + $result = $this->_rateResultFactory->create(); $am = $this->getAllowedMethods(); foreach ($am as $key => $_) { if ($this->getConfigData($key)) { - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + /** @var \Magento\Framework\App\State $state */ $state = $objectManager->get('\Magento\Framework\App\State'); $_pricIncl = $this->getConfigData('price_incl'); if ($state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) { @@ -122,7 +129,6 @@ public function collectRates(RateRequest $request) $total = $object->getQuote()->getSubtotal(); $grandTotal = $object->getQuote()->getGrandTotal(); } else { - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $total = $objectManager->create('\Magento\Checkout\Model\Session') ->getQuote()->getSubtotal(); @@ -153,7 +159,7 @@ public function collectRates(RateRequest $request) if (is_null($pricerule['btw_tarief'])) { $pricerule['btw_tarief'] = 0; } - $shippingPrice = ( (float)$pricerule['btw_tarief'] ? ( (float)$pricerule['price'] + ((float)$pricerule['price'] / 100 ) * (float)$pricerule['btw_tarief'] ) : (float)$pricerule['price'] ); + $shippingPrice = ((float)$pricerule['btw_tarief'] ? ((float)$pricerule['price'] + ((float)$pricerule['price'] / 100) * (float)$pricerule['btw_tarief']) : (float)$pricerule['price']); break; } } @@ -164,9 +170,45 @@ public function collectRates(RateRequest $request) $method->setCarrier($this->_code); if (strpos(strtolower($key), 'postnl') !== false) { - $method->setCarrierTitle('PostNL'); + $carrierTitle = 'PostNL'; + + if ($this->getConfigData('postnl_show_expected_delivery_date')) { + $sendDay = new DateTime(); + if (!$this->isBeforeLastShippingTime($this->getConfigData('postnl_last_shipping_time'))) { + $sendDay->add(new DateInterval('P1D')); + } + + $deliveryDate = $this->getDeliveryDate( + 'PostNL', + $sendDay, + $shippingAddress->getPostcode() + ); + + if ($deliveryDate) { + $carrierTitle .= ' (' . $this->formatDeliveryDate($deliveryDate) . ')'; + } + } + $method->setCarrierTitle($carrierTitle); } elseif (strpos(strtolower($key), 'dhl') !== false) { - $method->setCarrierTitle('DHL'); + $carrierTitle = 'DHL'; + + if ($this->getConfigData('dhl_show_expected_delivery_date')) { + $sendDay = new DateTime(); + if (!$this->isBeforeLastShippingTime($this->getConfigData('dhl_last_shipping_time'))) { + $sendDay->add(new DateInterval('P1D')); + } + + $deliveryDate = $this->getDeliveryDate( + 'DHL', + $sendDay, + $shippingAddress->getPostcode() + ); + + if ($deliveryDate) { + $carrierTitle .= ' (' . $this->formatDeliveryDate($deliveryDate) . ')'; + } + } + $method->setCarrierTitle($carrierTitle); } elseif (strpos(strtolower($key), 'vsp') !== false) { $method->setCarrierTitle('Van Straaten Post'); } elseif (strpos(strtolower($key), 'sameday') !== false) { @@ -192,7 +234,7 @@ public function collectRates(RateRequest $request) if (is_null($pricerule['btw_tarief'])) { $pricerule['btw_tarief'] = 0; } - $shippingPrice = ( (float)$pricerule['btw_tarief'] ? ( (float)$pricerule['price'] + ((float)$pricerule['price'] / 100 ) * (float)$pricerule['btw_tarief'] ) : (float)$pricerule['price'] ); + $shippingPrice = ((float)$pricerule['btw_tarief'] ? ((float)$pricerule['price'] + ((float)$pricerule['price'] / 100) * (float)$pricerule['btw_tarief']) : (float)$pricerule['price']); if ($shippingPrice !== false) { $method = $this->_rateMethodFactory->create(); @@ -217,4 +259,92 @@ public function collectRates(RateRequest $request) } return $result; } + + private function getDeliveryDate(string $carrier, \DateTimeInterface $dateTime, $postcode) + { + if (!$postcode) { + return false; + } + + $date = $dateTime->format('Y-m-d'); + $userId = $this->getConfigData('gebruiker_id'); + $apiKey = $this->getConfigData('api_key'); + + $query = http_build_query([ + 'Startdatum' => $date, + 'Postcode' => $postcode, + 'GebruikerId' => $userId, + 'Map' => true, + ]); + + $curlHandle = curl_init(); + curl_setopt_array($curlHandle, [ + CURLOPT_URL => $this->apiUrl . '/api/v3/timeframes.php?' . $query, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/json', + 'Digest: ' . hash_hmac( + "sha256", + sprintf('GebruikerId=%sPostcode=%sStartdatum=%s', $userId, $postcode, $date), + $apiKey + ), + ], + CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_HEADER => false, + CURLOPT_RETURNTRANSFER => true, + ]); + + $responseBody = curl_exec($curlHandle); + $responseCode = curl_getinfo($curlHandle, CURLINFO_RESPONSE_CODE); + + curl_close($curlHandle); + + if ($responseCode !== 200) { + $this->_logger->error(sprintf( + 'Failed to get expected delivery date, response code %s, body:\n%s', + $responseCode, + $responseBody + )); + return false; + } + + $responseJson = json_decode($responseBody, true); + $rawDate = $responseJson[$carrier]['Date'] ?? false; + + if (!$rawDate) { + $this->_logger->error(sprintf( + 'Failed to get expected delivery date, body:\n%s', + $responseBody + )); + return false; + } + + return \DateTimeImmutable::createFromFormat('Y-m-d', $rawDate); + } + + private function formatDeliveryDate(\DateTimeInterface $date) + { + $locale = $this->localeResolver->getLocale(); + return \IntlDateFormatter::formatObject($date, 'd MMMM', $locale); + } + + private function isBeforeLastShippingTime($rawLastTime): bool + { + if (!$rawLastTime) { + return true; + } + + try { + $parsed = new DateTime($rawLastTime); + } catch (\Exception $e) { + $this->_logger->error(sprintf( + 'Failed to parse last shipping time (%s): %s', + $rawLastTime, + $e->getMessage() + )); + return true; + } + + $now = new DateTime(); + return $now < $parsed; + } } diff --git a/composer.json b/composer.json index 97ea0f5..e1e5b92 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "parcelpro/shipment", "description": "Verzendmodule om gemakkelijk orders in te laden in het verzendsysteem van Parcel Pro.", - "version": "2.17.2", + "version": "2.18.0", "keywords": [ "verzenden", "pakket", @@ -11,7 +11,10 @@ ], "type": "magento2-module", "require": { - "php": ">=7.1" + "php": ">=7.1", + "ext-json": "*", + "ext-curl": "*", + "ext-intl": "*" }, "license": [ "OSL-3.0" @@ -35,7 +38,7 @@ "require-dev": { "squizlabs/php_codesniffer": "^3.7", "magento/community-edition": "^2.4", - "phpmd/phpmd": "^2.14" + "phpmd/phpmd": "^2.15" }, "config": { "allow-plugins": { diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 0bdc58e..5e74a41 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -9,7 +9,7 @@ - 2.17.2 + 2.18.0 @@ -62,6 +62,16 @@ + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + Parcelpro\Shipment\Block\Adminhtml\System\Config\Form\Field\Countriesmap @@ -106,6 +116,16 @@ + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + Parcelpro\Shipment\Block\Adminhtml\System\Config\Form\Field\Countriesmap diff --git a/install.sh b/install.sh index 212c76e..6aabd17 100755 --- a/install.sh +++ b/install.sh @@ -26,8 +26,8 @@ dx php bin/magento module:enable --clear-static-content Parcelpro_Shipment dx rm -r generated # Update the Magento setup and flush the cache. -dx php bin/magento setup:upgrade dx php bin/magento setup:di:compile +dx php bin/magento setup:upgrade dx php bin/magento setup:static-content:deploy -f dx php bin/magento cache:clean dx php bin/magento cache:flush