From f8e24627793bfb48e397921fa8a9cd77bdf08dff Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Mon, 1 Mar 2021 09:05:58 +0100 Subject: [PATCH 1/4] Reload widget on coupon usage in last checkout step --- Api/Data/CheckQuoteResultInterface.php | 52 ++++++ Model/Api/Converter/ShippingOptions.php | 52 ++++++ Model/Carrier/Paazlshipping.php | 2 +- Model/Checkout/WidgetConfigProvider.php | 27 ++- Model/Quote/CheckQuoteShippingOption.php | 156 ++++++++++++++++++ Model/Webapi/CheckShippingOption.php | 123 ++++++++++++++ Model/Webapi/CheckShippingOption/Result.php | 62 +++++++ Model/Webapi/GuestCheckShippingOption.php | 51 ++++++ etc/webapi.xml | 21 +++ view/frontend/requirejs-config.js | 6 + .../checkout/action/check-shipping-option.js | 47 ++++++ .../web/js/checkout/view/widget-config.js | 27 ++- .../action/cancel-coupon-mixin.js | 31 ++++ .../action/set-coupon-code-mixin.js | 35 ++++ 14 files changed, 685 insertions(+), 7 deletions(-) create mode 100644 Api/Data/CheckQuoteResultInterface.php create mode 100644 Model/Api/Converter/ShippingOptions.php create mode 100644 Model/Quote/CheckQuoteShippingOption.php create mode 100644 Model/Webapi/CheckShippingOption.php create mode 100644 Model/Webapi/CheckShippingOption/Result.php create mode 100644 Model/Webapi/GuestCheckShippingOption.php create mode 100644 etc/webapi.xml create mode 100644 view/frontend/web/js/checkout/action/check-shipping-option.js create mode 100644 view/frontend/web/js/mixins/Magento_SalesRule/action/cancel-coupon-mixin.js create mode 100644 view/frontend/web/js/mixins/Magento_SalesRule/action/set-coupon-code-mixin.js diff --git a/Api/Data/CheckQuoteResultInterface.php b/Api/Data/CheckQuoteResultInterface.php new file mode 100644 index 0000000..2dec938 --- /dev/null +++ b/Api/Data/CheckQuoteResultInterface.php @@ -0,0 +1,52 @@ +json = $json; + $this->generalHelper = $generalHelper; + } + + /** + * @param string|null $response + * @return array|null + */ + public function convert($response) + { + try { + return $this->json->unserialize($response); + } catch (\InvalidArgumentException $e) { + $this->generalHelper->addTolog('exception', $e->getMessage()); + } + + return null; + } +} diff --git a/Model/Carrier/Paazlshipping.php b/Model/Carrier/Paazlshipping.php index cc4dba4..98b0b0a 100755 --- a/Model/Carrier/Paazlshipping.php +++ b/Model/Carrier/Paazlshipping.php @@ -230,4 +230,4 @@ private function extractQuote(RateRequest $request) return $quote; } -} \ No newline at end of file +} diff --git a/Model/Checkout/WidgetConfigProvider.php b/Model/Checkout/WidgetConfigProvider.php index 22e262c..9ef5bf7 100644 --- a/Model/Checkout/WidgetConfigProvider.php +++ b/Model/Checkout/WidgetConfigProvider.php @@ -72,6 +72,11 @@ class WidgetConfigProvider implements ConfigProviderInterface */ private $productRepository; + /** + * @var Quote + */ + private $quote; + /** * Widget constructor. * @@ -169,9 +174,9 @@ public function getConfig() "sortOrder" => "ASC" ], "shipmentParameters" => [ - "totalWeight" => $this->getTotalWeight(), - "totalPrice" => $this->getQuote()->getSubtotalWithDiscount(), - "numberOfGoods" => $this->getProductsCount(), + "totalWeight" => (float)$this->getTotalWeight(), + "totalPrice" => (float)$this->getQuote()->getSubtotalWithDiscount(), + "numberOfGoods" => (int)$this->getProductsCount(), "goods" => $goods ], "shippingOptionsLimit" => $this->getShippingOptionsLimit(), @@ -192,7 +197,21 @@ public function getConfig() */ public function getQuote() { - return $this->checkoutHelper->getQuote(); + if (!$this->quote) { + return $this->checkoutHelper->getQuote(); + } + + return $this->quote; + } + + /** + * @param Quote|null $quote + * @return $this + */ + public function setQuote(Quote $quote = null) + { + $this->quote = $quote; + return $this; } /** diff --git a/Model/Quote/CheckQuoteShippingOption.php b/Model/Quote/CheckQuoteShippingOption.php new file mode 100644 index 0000000..8fc8926 --- /dev/null +++ b/Model/Quote/CheckQuoteShippingOption.php @@ -0,0 +1,156 @@ +extInfoHandler = $extInfoHandler; + $this->apiFactory = $apiFactory; + $this->configProvider = $configProvider; + $this->generalHelper = $generalHelper; + $this->shippingOptionsConverter = $shippingOptionsConverter; + } + + /** + * @param Quote|CartInterface $quote + * @return DataObject + */ + public function validate(Quote $quote) + { + $result = new DataObject(); + if (!$quote->getShippingAddress()) { + return $result; + } + + $method = (string)$quote->getShippingAddress()->getShippingMethod(); + if (strpos($method, Paazlshipping::CODE) === false) { + return $result; + } + + $info = $this->extInfoHandler->getInfoFromQuote($quote); + if (!$info) { + return $result; + } + + $optionIdentifier = $info->getIdenfifier(); + if (($info->getType() !== DeliveryType::DELIVERY) || empty($optionIdentifier)) { + return $result; + } + + // Re-retrieving shipping options from API + $api = $this->apiFactory->create($quote->getStoreId()); + try { + $config = $this->configProvider->setQuote($quote)->getConfig(); + + $shippingOptions = $this->shippingOptionsConverter->convert( + $api->getShippingOptions($config) + ); + } catch (LocalizedException $e) { + $this->generalHelper->addTolog('CheckQuoteShippingOption exception: ' . $e->getLogMessage(), [ + 'quoteId' => $quote->getId() + ]); + return $result; + } catch (Exception $e) { + $this->generalHelper->addTolog('CheckQuoteShippingOption exception: ' . $e->getMessage(), [ + 'quoteId' => $quote->getId() + ]); + return $result; + } + + $options = $shippingOptions['shippingOptions'] ?? []; + + $optionExists = false; + $optionExists = array_reduce($options, function ($carry, $item) use ($optionIdentifier) { + return $carry || (!empty($item['identifier']) && ($item['identifier'] == $optionIdentifier)); + }, $optionExists); + + if (!$optionExists) { + // Reset quote's shipping method to default one + $result->setReloadWidget(true); + return $result; + } + + $newPrice = null; + $newPrice = array_reduce($options, function ($carry, $item) use ($optionIdentifier) { + return (!empty($item['identifier']) + && ($item['identifier'] == $optionIdentifier) + && array_key_exists('rate', $item)) + ? (float)$item['rate'] + : $carry; + }, $newPrice); + + if ($newPrice !== null && $newPrice !== (float)$info->getPrice()) { + // Price has changed - update info + recollect quote totals + $info->setPrice($newPrice); + $this->extInfoHandler->setInfoToQuote($info, $quote); + $result->setRecollectTotals(true); + return $result; + } + + return $result; + } +} diff --git a/Model/Webapi/CheckShippingOption.php b/Model/Webapi/CheckShippingOption.php new file mode 100644 index 0000000..09de454 --- /dev/null +++ b/Model/Webapi/CheckShippingOption.php @@ -0,0 +1,123 @@ +checkQuoteShippingOption = $checkQuoteShippingOption; + $this->cartRepository = $cartRepository; + $this->resultFactory = $resultFactory; + $this->totalRepository = $totalRepository; + $this->widgetConfigProviderFactory = $widgetConfigProviderFactory; + $this->json = $json; + $this->generalHelper = $generalHelper; + } + + /** + * @param integer $cartId + * @return \Paazl\CheckoutWidget\Api\Data\CheckQuoteResultInterface + * @throws NoSuchEntityException + */ + public function get($cartId) + { + $quote = $this->cartRepository->getActive($cartId); + $checkResult = $this->checkQuoteShippingOption->validate($quote); + + /** @var Result $result */ + $result = $this->resultFactory->create(); + + if ($checkResult->getReloadWidget()) { + $result->setReloadWidget(true); + } + + if ($checkResult->getRecollectTotals()) { + $quote->collectTotals(); + $this->cartRepository->save($quote); + $result->setTotals($this->totalRepository->get($cartId)); + } + + try { + /** @var WidgetConfigProvider $config */ + $config = $this->widgetConfigProviderFactory->create(); + $config->setQuote($quote); + $result->setReloadWidgetConfigJson($this->json->serialize($config->getConfig())); + } catch (LocalizedException $e) { + $this->generalHelper->addTolog('exception', $e->getLogMessage()); + } + + return $result; + } +} diff --git a/Model/Webapi/CheckShippingOption/Result.php b/Model/Webapi/CheckShippingOption/Result.php new file mode 100644 index 0000000..669134d --- /dev/null +++ b/Model/Webapi/CheckShippingOption/Result.php @@ -0,0 +1,62 @@ +_get(self::RELOAD_WIDGET); + } + + /** + * @inheritDoc + */ + public function setReloadWidget($value) + { + return $this->setData(self::RELOAD_WIDGET, (bool)$value); + } + + /** + * @inheritDoc + */ + public function getTotals() + { + return $this->_get(self::TOTALS); + } + + /** + * @inheritDoc + */ + public function setTotals($value) + { + return $this->setData(self::TOTALS, $value); + } + + /** + * @inheritDoc + */ + public function getReloadWidgetConfigJson(): string + { + return (string)$this->_get(self::RELOAD_WIDGET_CONFIG_JSON); + } + + /** + * @inheritDoc + */ + public function setReloadWidgetConfigJson(string $value) + { + return $this->setData(self::RELOAD_WIDGET_CONFIG_JSON, $value); + } +} diff --git a/Model/Webapi/GuestCheckShippingOption.php b/Model/Webapi/GuestCheckShippingOption.php new file mode 100644 index 0000000..f97ad34 --- /dev/null +++ b/Model/Webapi/GuestCheckShippingOption.php @@ -0,0 +1,51 @@ +quoteIdMaskFactory = $quoteIdMaskFactory; + $this->checkShippingOption = $checkShippingOption; + } + + /** + * @param string $cartId + * @return \Paazl\CheckoutWidget\Api\Data\CheckQuoteResultInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function get($cartId) + { + /** @var $quoteIdMask QuoteIdMask */ + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); + return $this->checkShippingOption->get($quoteIdMask->getQuoteId()); + } +} diff --git a/etc/webapi.xml b/etc/webapi.xml new file mode 100644 index 0000000..eacc5a6 --- /dev/null +++ b/etc/webapi.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + %cart_id% + + + diff --git a/view/frontend/requirejs-config.js b/view/frontend/requirejs-config.js index 179c019..23d743f 100755 --- a/view/frontend/requirejs-config.js +++ b/view/frontend/requirejs-config.js @@ -35,6 +35,12 @@ var config = { }, 'Onestepcheckout_Iosc/js/shipping': { 'Paazl_CheckoutWidget/js/mixins/Onestepcheckout_Iosc/shipping-mixin': true + }, + 'Magento_SalesRule/js/action/set-coupon-code': { + 'Paazl_CheckoutWidget/js/mixins/Magento_SalesRule/action/set-coupon-code-mixin': true + }, + 'Magento_SalesRule/js/action/cancel-coupon': { + 'Paazl_CheckoutWidget/js/mixins/Magento_SalesRule/action/cancel-coupon-mixin': true } } } diff --git a/view/frontend/web/js/checkout/action/check-shipping-option.js b/view/frontend/web/js/checkout/action/check-shipping-option.js new file mode 100644 index 0000000..be34744 --- /dev/null +++ b/view/frontend/web/js/checkout/action/check-shipping-option.js @@ -0,0 +1,47 @@ +define( + [ + 'Magento_Checkout/js/model/step-navigator', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/resource-url-manager', + 'mage/storage', + 'Paazl_CheckoutWidget/js/checkout/view/widget-config' + ], + function (stepNavigator, quote, resourceUrl, storage, widgetConfig) { + return function () { + var shippingMethod = quote.shippingMethod(); + if (widgetConfig.prototype.getCarrierCode() !== shippingMethod.carrier_code + || widgetConfig.prototype.getMethodCode() !== shippingMethod.method_code) { + return; + } + + var params = (resourceUrl.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {}, + urls = { + 'guest': '/guest-carts/' + quote.getQuoteId() + '/paazl-check-shipping-option', + 'customer': '/carts/mine/paazl-check-shipping-option' + }, + url = resourceUrl.getUrl(urls, params); + + storage.get( + url, + {}, + false + ).done(function (response) { + if (response.reload_widget_config_json) { + var newConfig; + try { + newConfig = JSON.parse(response.reload_widget_config_json); + } catch (e) {} + widgetConfig.prototype.reloadWidget(newConfig); + } + + if (response.reload_widget === true) { + stepNavigator.navigateTo('shipping', 'opc-shipping_method'); + } + + if (response.totals !== null && response.totals !== undefined) { + quote.setTotals(response.totals); + } + }); + } + } +); diff --git a/view/frontend/web/js/checkout/view/widget-config.js b/view/frontend/web/js/checkout/view/widget-config.js index 8775da1..432f470 100755 --- a/view/frontend/web/js/checkout/view/widget-config.js +++ b/view/frontend/web/js/checkout/view/widget-config.js @@ -69,7 +69,7 @@ define([ } return Component.extend({ - configJson: {}, + configJson: null, customerAddressId: null, locked: false, state: { @@ -83,7 +83,7 @@ define([ }, initWidget: function () { - this.configJson = widgetConfig || {}; + this.configJson = this.configJson || widgetConfig; this.initMap(); }, @@ -191,6 +191,29 @@ define([ self.customerAddressId = quote.shippingAddress()['customerAddressId']; + require([this.getJsName()], infoUpdate); + }, + + reloadWidget: function (data) { + this.initWidget(); + data = data || this.configJson; + + if (!data) { + return; + } + this.configJson = data; + console.log(this.configJson); + var container = $('#' + data.mountElementId); + + if (!container.length || !container.data('paazlactive')) { + return; + } + + var infoUpdate = function (paazlCheckout) { + container.html(''); + paazlCheckout.init(data); + }; + require([this.getJsName()], infoUpdate); } }); diff --git a/view/frontend/web/js/mixins/Magento_SalesRule/action/cancel-coupon-mixin.js b/view/frontend/web/js/mixins/Magento_SalesRule/action/cancel-coupon-mixin.js new file mode 100644 index 0000000..3fd7c2c --- /dev/null +++ b/view/frontend/web/js/mixins/Magento_SalesRule/action/cancel-coupon-mixin.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2019 Paazl. All rights reserved. + * See COPYING.txt for license details. + */ + +define( + [ + 'mage/utils/wrapper', + 'Paazl_CheckoutWidget/js/checkout/action/check-shipping-option' + ], + function (wrapper, checkShippingOption) { + return function (target) { + + // Compatibility with 2.4 + if (target.hasOwnProperty('registerSuccessCallback') + && (typeof target.registerSuccessCallback === 'function')) { + target.registerSuccessCallback(function () { + checkShippingOption(); + }); + + return target; + } + + return wrapper.wrap(target, function (orig) { + return orig().done(function () { + checkShippingOption(); + }); + }); + }; + } +); diff --git a/view/frontend/web/js/mixins/Magento_SalesRule/action/set-coupon-code-mixin.js b/view/frontend/web/js/mixins/Magento_SalesRule/action/set-coupon-code-mixin.js new file mode 100644 index 0000000..d35e6dd --- /dev/null +++ b/view/frontend/web/js/mixins/Magento_SalesRule/action/set-coupon-code-mixin.js @@ -0,0 +1,35 @@ +/** + * Copyright © 2019 Paazl. All rights reserved. + * See COPYING.txt for license details. + */ + +define( + [ + 'mage/utils/wrapper', + 'Paazl_CheckoutWidget/js/checkout/action/check-shipping-option' + ], + function (wrapper, checkShippingOption) { + return function (target) { + + // Compatibility with 2.4 + if (target.hasOwnProperty('registerSuccessCallback') + && (typeof target.registerSuccessCallback === 'function')) { + target.registerSuccessCallback(function (response) { + checkShippingOption(); + }); + + return target; + } + + return wrapper.wrap(target, function (orig) { + return orig().done(function (couponResponse) { + if (!couponResponse) { + return; + } + + checkShippingOption(); + }); + }); + }; + } +); From 5f29c9cb92c290bd22deead03f0348d10f158c57 Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Mon, 1 Mar 2021 09:14:22 +0100 Subject: [PATCH 2/4] Fix for warning when Zero is provided as address --- Model/Api/Builder/Order.php | 14 +++++++--- Test/Unit/Model/Api/Builder/OrderTest.php | 31 +++++++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Model/Api/Builder/Order.php b/Model/Api/Builder/Order.php index 5be6699..1ba16e5 100755 --- a/Model/Api/Builder/Order.php +++ b/Model/Api/Builder/Order.php @@ -234,7 +234,7 @@ public function parseAddress(Address $shippingAddress) if (!trim($parser)) { continue; } - if (!preg_match('~[0-9]+~' , $parser) + if (!preg_match('~[0-9]+~', $parser) && strlen($parser) > 2) { $probably['street'][] = $parser; } elseif (ctype_digit($parser)) { @@ -254,9 +254,15 @@ public function parseAddress(Address $shippingAddress) } $probably = [ - 'street' => implode(' ', $probably['street']), - 'houseNumber' => implode('', $probably['houseNumber']), - 'houseNumberExtension' => implode('', $probably['houseNumberExtension']) + 'street' => is_array($probably['street']) + ? implode(' ', $probably['street']) + : $probably['street'], + 'houseNumber' => is_array($probably['houseNumber']) + ? implode('', $probably['houseNumber']) + : $probably['houseNumber'], + 'houseNumberExtension' => is_array($probably['houseNumberExtension']) + ? implode('', $probably['houseNumberExtension']) + : $probably['houseNumberExtension'] ]; if ($probably['street'] && $probably['houseNumber']) { return $probably; diff --git a/Test/Unit/Model/Api/Builder/OrderTest.php b/Test/Unit/Model/Api/Builder/OrderTest.php index 48a27ef..1e34516 100644 --- a/Test/Unit/Model/Api/Builder/OrderTest.php +++ b/Test/Unit/Model/Api/Builder/OrderTest.php @@ -6,6 +6,7 @@ namespace Paazl\CheckoutWidget\Test\Unit\Model\Api\Builder; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Model\Order\Address; @@ -189,10 +190,26 @@ public function parseAddressProvider(): array public function testParseAddressUnknown(array $street, array $expect) { $addressMock = $this->getMockBuilder(Address::class)->disableOriginalConstructor()->getMock(); - $addressMock->expects($this->once())->method('getStreet')->willReturn($street); + $addressMock->expects($this->atLeastOnce())->method('getStreet')->willReturn($street); + $this->configMock->method('getHouseNumberDefaultOption')->willReturn(false); + $this->expectException(LocalizedException::class); $result = $this->entity->parseAddress($addressMock); + } + + /** + * @param array $street + * @param array $expect + * + * @dataProvider parseAddressUnknownProvider + */ + public function testParseAddressUnknownDefaultHousenumber(array $street, array $expect) + { + $addressMock = $this->getMockBuilder(Address::class)->disableOriginalConstructor()->getMock(); + $addressMock->expects($this->atLeastOnce())->method('getStreet')->willReturn($street); + $this->configMock->method('getHouseNumberDefaultOption')->willReturn(true); + $result = $this->entity->parseAddress($addressMock); $this->assertEquals($expect, $result); } @@ -201,15 +218,19 @@ public function parseAddressUnknownProvider(): array return [ [ ['spaarne'], - ['street' => 'spaarne', 'houseNumber' => '0', 'houseNumberExtension' => ''] + ['street' => 'spaarne', 'houseNumber' => null, 'houseNumberExtension' => null] ], [ [' Diemerkade str. '], - ['street' => 'Diemerkade str.', 'houseNumber' => '0', 'houseNumberExtension' => ''] + ['street' => 'Diemerkade str.', 'houseNumber' => null, 'houseNumberExtension' => null] ], [ ['Straat72test'], - ['street' => 'Straat72test', 'houseNumber' => '0', 'houseNumberExtension' => ''] + ['street' => 'Straat72test', 'houseNumber' => null, 'houseNumberExtension' => null] + ], + [ + ['', '', '0'], + ['street' => '0', 'houseNumber' => null, 'houseNumberExtension' => null] ], ]; } @@ -269,4 +290,4 @@ public function orderInsuredValueDataProvider() [201.36363, 'USD'], ]; } -} +} \ No newline at end of file From d14a3e34373d7e7975d18c876f5e69140c22941c Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Mon, 1 Mar 2021 09:14:44 +0100 Subject: [PATCH 3/4] Fixed Unit Test GitHub workflow --- .github/workflows/unit-test.yml | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index af58e86..700074b 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -1,25 +1,25 @@ - name: Unit Tests +name: Unit Tests - on: pull_request +on: pull_request - jobs: - build: - strategy: - matrix: - PHP_VERSION: [php71-fpm, php72-fpm] - MAGENTO_VERSION: [2.2.11, 2.3.4] - exclude: - - PHP_VERSION: php72-fpm - MAGENTO_VERSION: 2.2.11 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 +jobs: + build: + strategy: + matrix: + PHP_VERSION: [php71-fpm, php72-fpm] + MAGENTO_VERSION: [2.2.11, 2.3.4] + exclude: + - PHP_VERSION: php72-fpm + MAGENTO_VERSION: 2.2.11 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 - - name: Start Docker - run: PHP_VERSION=${{ matrix.PHP_VERSION }} MAGENTO_VERSION=magento${{ matrix.MAGENTO_VERSION }} docker-compose -f .github/workflows/templates/docker-compose.yml up -d + - name: Start Docker + run: PHP_VERSION=${{ matrix.PHP_VERSION }} MAGENTO_VERSION=magento${{ matrix.MAGENTO_VERSION }} docker-compose -f .github/workflows/templates/docker-compose.yml up -d - - name: Upload our code into the docker container - run: docker cp $(pwd)/. magento-project-community-edition:/data/extensions && docker exec magento-project-community-edition composer require paazl/magento2-checkout-widget:@dev + - name: Upload our code into the docker container + run: docker cp $(pwd)/. magento-project-community-edition:/data/extensions/workdir && docker exec magento-project-community-edition composer require paazl/magento2-checkout-widget:@dev - - name: Run tests - run: docker exec magento-project-community-edition bash -c "vendor/bin/phpunit extensions/Test/Unit" \ No newline at end of file + - name: Run tests + run: docker exec magento-project-community-edition bash -c "vendor/bin/phpunit extensions/workdir/Test/Unit" \ No newline at end of file From 94ddb312775a65266256444523bda674a7c27965 Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Mon, 1 Mar 2021 09:15:07 +0100 Subject: [PATCH 4/4] Version bump --- composer.json | 2 +- etc/config.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 92e9b7f..44670de 100755 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "paazl/magento2-checkout-widget", "description": "Paazl checkoutWidget for Magento 2", "type": "magento2-module", - "version": "1.4.0", + "version": "1.4.1", "keywords": [ "Paazl", "Magento 2", diff --git a/etc/config.xml b/etc/config.xml index 3aee724..3b0e2d5 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -8,7 +8,7 @@ - v1.4.0 + v1.4.1 0 0 0