diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7628614bec20a..8fcb71a54b72a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -344,6 +344,7 @@ GitHub contributors: - Georges Cubas - Gerdus van Zyl - ggedamed +- Giuseppe Tripiciano - Giant Leap Lab - Ginkosama - ginodev @@ -399,6 +400,7 @@ GitHub contributors: - indesign47 - Ines Sallemi - Inetbiz +- Inform-All - ironwo0d - Ish Gupta - Ishiki @@ -852,6 +854,7 @@ GitHub contributors: - Salim Benouamer - Sam Berry - sallemiines +- Salvo Passaro - Sam - Sam Sanchez - Samir Shah diff --git a/classes/Image.php b/classes/Image.php index 1d791d61fd054..3fe710dccd011 100644 --- a/classes/Image.php +++ b/classes/Image.php @@ -24,7 +24,6 @@ * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ -use PrestaShop\PrestaShop\Adapter\SymfonyContainer; use PrestaShop\PrestaShop\Core\Exception\InvalidArgumentException; use PrestaShop\PrestaShop\Core\Image\ImageFormatConfiguration; @@ -930,8 +929,6 @@ public function getPathForCreation() */ private function deleteAutoGeneratedImage(array $imageType, string $imageFormat, array $filesToDelete): array { - $configuration = SymfonyContainer::getInstance()->get('prestashop.adapter.legacy.configuration'); - // Regular thumbnail $filesToDelete[] = $this->image_dir . $this->getExistingImgPath() . '-' . $imageType['name'] . '.' . $imageFormat; @@ -939,8 +936,8 @@ private function deleteAutoGeneratedImage(array $imageType, string $imageFormat, $filesToDelete[] = $this->image_dir . $this->getExistingImgPath() . '-' . $imageType['name'] . '2x.' . $imageFormat; // Watermarked thumbnail, if present - if ($configuration->get('WATERMARK_HASH')) { - $filesToDelete[] = $this->image_dir . $this->getExistingImgPath() . '-' . $imageType['name'] . '-' . $configuration->get('WATERMARK_HASH') . '.' . $imageFormat; + if (Configuration::get('WATERMARK_HASH')) { + $filesToDelete[] = $this->image_dir . $this->getExistingImgPath() . '-' . $imageType['name'] . '-' . Configuration::get('WATERMARK_HASH') . '.' . $imageFormat; } return $filesToDelete; diff --git a/composer.json b/composer.json index 46c8ab91be371..4279736c730f5 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,7 @@ "prestashop/blockreassurance": "^5", "prestashop/blockwishlist": "^3.0", "prestashop/circuit-breaker": "^4.0", - "prestashop/classic": "^3", + "prestashop/classic": "~3.1.0", "prestashop/contactform": "^4", "prestashop/dashactivity": "^2", "prestashop/dashgoals": "^2", @@ -71,7 +71,7 @@ "prestashop/hummingbird": "^2.0", "prestashop/pagesnotfound": "^3", "prestashop/productcomments": "^8.0", - "prestashop/ps_apiresources": "dev-add-combinations-endpoint", + "prestashop/ps_apiresources": "dev-add-discountType-resource", "prestashop/ps_banner": "^2", "prestashop/ps_bestsellers": "^1.0", "prestashop/ps_brandlist": "^1.0", @@ -212,7 +212,7 @@ }, "ps_apiresources": { "type": "vcs", - "url": "https://github.com/sebajps/ps_apiresources" + "url": "https://github.com/PrestaShop/ps_apiresources" } }, "minimum-stability": "dev", diff --git a/composer.lock b/composer.lock index cf75a70b67569..bf1d03bf5b622 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3d51d2e720417b2662928b43e3a23ad7", + "content-hash": "a432fafce6e80f362185427cad5f4b8d", "packages": [ { "name": "api-platform/core", @@ -4662,16 +4662,16 @@ }, { "name": "prestashop/classic", - "version": "3.0.5", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/PrestaShop/classic-theme.git", - "reference": "09a8934bcb5e8f0cc0a3e234d5e9b18a61c27ec2" + "reference": "9af074d6cdbb8002323780e85b11e30d210f002b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/classic-theme/zipball/09a8934bcb5e8f0cc0a3e234d5e9b18a61c27ec2", - "reference": "09a8934bcb5e8f0cc0a3e234d5e9b18a61c27ec2", + "url": "https://api.github.com/repos/PrestaShop/classic-theme/zipball/9af074d6cdbb8002323780e85b11e30d210f002b", + "reference": "9af074d6cdbb8002323780e85b11e30d210f002b", "shasum": "" }, "require-dev": { @@ -4696,9 +4696,9 @@ "description": "Classic theme for develop PrestaShop version", "support": { "issues": "https://github.com/PrestaShop/classic-theme/issues", - "source": "https://github.com/PrestaShop/classic-theme/tree/3.0.5" + "source": "https://github.com/PrestaShop/classic-theme/tree/3.1.0" }, - "time": "2025-12-15T16:49:50+00:00" + "time": "2026-01-16T10:02:47+00:00" }, { "name": "prestashop/contactform", @@ -5083,16 +5083,16 @@ }, { "name": "prestashop/hummingbird", - "version": "v2.0.0-beta.2", + "version": "v2.0.0-beta.3", "source": { "type": "git", "url": "https://github.com/PrestaShop/hummingbird.git", - "reference": "d2576caa72ca08468ea372ce6f133f8ac52dacb2" + "reference": "9732762a0d7b88b6b40a4c9d36b299e52deedaff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/hummingbird/zipball/d2576caa72ca08468ea372ce6f133f8ac52dacb2", - "reference": "d2576caa72ca08468ea372ce6f133f8ac52dacb2", + "url": "https://api.github.com/repos/PrestaShop/hummingbird/zipball/9732762a0d7b88b6b40a4c9d36b299e52deedaff", + "reference": "9732762a0d7b88b6b40a4c9d36b299e52deedaff", "shasum": "" }, "require-dev": { @@ -5117,9 +5117,9 @@ "description": "Hummingbird development theme for PrestaShop", "support": { "issues": "https://github.com/PrestaShop/hummingbird/issues", - "source": "https://github.com/PrestaShop/hummingbird/tree/v2.0.0-beta.2" + "source": "https://github.com/PrestaShop/hummingbird/tree/v2.0.0-beta.3" }, - "time": "2025-12-15T17:19:33+00:00" + "time": "2026-01-21T14:00:19+00:00" }, { "name": "prestashop/pagesnotfound", @@ -5208,16 +5208,16 @@ }, { "name": "prestashop/ps_apiresources", - "version": "dev-add-combinations-endpoint", + "version": "dev-add-discountType-resource", "source": { "type": "git", - "url": "https://github.com/sebajps/ps_apiresources.git", - "reference": "86e47474aa9004dfeaf7b726bfb192e66ab15779" + "url": "https://github.com/PrestaShop/ps_apiresources.git", + "reference": "f7d72022404d9c03691e3d63bde7ccae2f26a04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebajps/ps_apiresources/zipball/86e47474aa9004dfeaf7b726bfb192e66ab15779", - "reference": "86e47474aa9004dfeaf7b726bfb192e66ab15779", + "url": "https://api.github.com/repos/PrestaShop/ps_apiresources/zipball/f7d72022404d9c03691e3d63bde7ccae2f26a04a", + "reference": "f7d72022404d9c03691e3d63bde7ccae2f26a04a", "shasum": "" }, "require": { @@ -5281,9 +5281,10 @@ "description": "PrestaShop - API Resources", "homepage": "https://github.com/PrestaShop/ps_apiresources", "support": { - "source": "https://github.com/sebajps/ps_apiresources/tree/add-combinations-endpoint" + "source": "https://github.com/PrestaShop/ps_apiresources/tree/add-discountType-resource", + "issues": "https://github.com/PrestaShop/ps_apiresources/issues" }, - "time": "2026-01-21T07:13:47+00:00" + "time": "2026-01-28T06:41:30+00:00" }, { "name": "prestashop/ps_banner", @@ -6002,16 +6003,16 @@ }, { "name": "prestashop/ps_facetedsearch", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/PrestaShop/ps_facetedsearch.git", - "reference": "8ebc5f07be387e378baf907a02f53f1496e6347b" + "reference": "bd9f09e81d1d49a936b4c0c3fa6b7e846bc53e76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/ps_facetedsearch/zipball/8ebc5f07be387e378baf907a02f53f1496e6347b", - "reference": "8ebc5f07be387e378baf907a02f53f1496e6347b", + "url": "https://api.github.com/repos/PrestaShop/ps_facetedsearch/zipball/bd9f09e81d1d49a936b4c0c3fa6b7e846bc53e76", + "reference": "bd9f09e81d1d49a936b4c0c3fa6b7e846bc53e76", "shasum": "" }, "require": { @@ -6047,9 +6048,10 @@ "description": "PrestaShop module ps_facetedsearch", "homepage": "https://github.com/PrestaShop/ps_facetedsearch", "support": { - "source": "https://github.com/PrestaShop/ps_facetedsearch/tree/v4.0.2" + "issues": "https://github.com/PrestaShop/ps_facetedsearch/issues", + "source": "https://github.com/PrestaShop/ps_facetedsearch/tree/v4.0.3" }, - "time": "2025-11-21T13:36:43+00:00" + "time": "2025-12-31T13:27:28+00:00" }, { "name": "prestashop/ps_faviconnotificationbo", @@ -18271,5 +18273,5 @@ "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php index c7cadb3cd2bc0..732d0b5f5cd83 100644 --- a/controllers/front/ProductController.php +++ b/controllers/front/ProductController.php @@ -454,11 +454,11 @@ public function displayAjaxQuickview(): void public function displayAjaxRefresh(): void { $product = $this->getTemplateVarProduct(); - $minimalProductQuantity = $this->getProductMinimalQuantity($product); - // If the product is already in the cart, we can set the minimal quantity to 1 - if ($product['cart_quantity'] >= $minimalProductQuantity) { - $minimalProductQuantity = 1; + // After refresh, we will show the customer a new quantity he has to use + $newMinimalQuantity = $product['quantity_required']; + if (empty($newMinimalQuantity)) { + $newMinimalQuantity = 1; } ob_end_clean(); @@ -496,7 +496,8 @@ public function displayAjaxRefresh(): void 'adtoken' => Tools::getValue('adtoken'), ] : [] ), - 'product_minimal_quantity' => $minimalProductQuantity, + // A new minimal quantity to use on the input after refresh + 'product_minimal_quantity' => $newMinimalQuantity, 'product_has_combinations' => !empty($this->combinations), 'id_product_attribute' => $product['id_product_attribute'], 'id_customization' => $product['id_customization'], @@ -1182,33 +1183,57 @@ private function getIdProductAttributeByGroup(): ?int public function getTemplateVarProduct(): ProductLazyArray { - $productSettings = $this->getProductPresentationSettings(); - // Hook displayProductExtraContent - $extraContentFinder = new ProductExtraContentFinder(); - + // Convert product object into array $product = $this->objectPresenter->present($this->product); + + // Assign several product properties to the array $product['description'] = $this->transformDescriptionWithImg($this->product->description); + + /* + * This property is not a product property, but value from stock_available table. It must be here because on this page, + * it's not initialized in any other way. On listings, it goes through ProductAssembler and the property is included. + * In cart, it's also in the selected fields. But not here. + * + * We could centralize it right now, but the call StockAvailable::outOfStock($this->id) would still be called + * when constructing a Product object, so, let's just migrate it all at once later. + */ $product['out_of_stock'] = (int) $this->product->out_of_stock; $product['id_product_attribute'] = $this->getIdProductAttributeByGroupOrRequestOrDefault(); + + // @todo These three properties should be migrated into the lazy array, so they are available also in listings + // Minimal quantity setting of this product or combination $product['minimal_quantity'] = $this->getProductMinimalQuantity($product); + + // Quantity of this product in the current cart $product['cart_quantity'] = $this->context->cart->getProductQuantity((int) $this->product->id, $product['id_product_attribute'])['quantity']; - $product['quantity_wanted'] = $this->getRequiredQuantity($product); - $product['extraContent'] = $extraContentFinder->addParams(['product' => $this->product])->present(); + + // Quantity requested by the customer by the quantity input on product page - may be force-altered by us + // @todo - a centralized version of this method is implemented in ProductLazyArray - migrate to it when migrating this code + $product['quantity_wanted'] = $this->getWantedQuantity($product); + + // Required quantity to add to cart to reach minimal quantity + // @todo - a centralized version of this method is implemented in ProductLazyArray - migrate to it when migrating this code + $product['quantity_required'] = $this->getRequiredQuantity($product); + + // Render hook displayProductExtraContent + $product['extraContent'] = (new ProductExtraContentFinder())->addParams(['product' => $this->product])->present(); $product['ecotax_tax_inc'] = $this->product->getEcotax(null, true, true); $product['ecotax'] = Tools::convertPrice($this->getProductEcotax($product), $this->context->currency, true, $this->context); + // Enrich the product array $product_full = Product::getProductProperties($this->context->language->id, $product, $this->context); + // Add possible customizations $product_full = $this->addProductCustomizationData($product_full); $product_full['show_quantities'] = (bool) ( Configuration::get('PS_DISPLAY_QTIES') && Configuration::get('PS_STOCK_MANAGEMENT') - && $this->product->quantity > 0 + && $product_full['quantity'] > 0 && $this->product->available_for_order && !Configuration::isCatalogMode() ); - $product_full['quantity_label'] = ($this->product->quantity > 1) ? $this->trans('Items', [], 'Shop.Theme.Catalog') : $this->trans('Item', [], 'Shop.Theme.Catalog'); + $product_full['quantity_label'] = ($product_full['quantity'] > 1) ? $this->trans('Items', [], 'Shop.Theme.Catalog') : $this->trans('Item', [], 'Shop.Theme.Catalog'); $product_full['quantity_discounts'] = $this->quantity_discounts; $group_reduction = GroupReduction::getValueForProduct($this->product->id, (int) Group::getCurrent()->id); @@ -1218,32 +1243,42 @@ public function getTemplateVarProduct(): ProductLazyArray $product_full['customer_group_discount'] = $group_reduction; $product_full['title'] = $this->getProductPageTitle(); + // And finally, present it in the modern way return $this->getProductPresenter()->present( - $productSettings, + $this->getProductPresentationSettings(), $product_full, $this->context->language ); } /** + * Gets the minimal quantity allowed for the product or its combination. With no adjustments + * by the current context. + * + * @todo This method should be migrated to ProductLazyArray, so it's available also in listings. + * * @param array $product * - * @return int + * @return int Minimal quantity of product from it's settings, always a positive integer */ protected function getProductMinimalQuantity(ProductLazyArray|array $product) { - $minimal_quantity = 1; + $minimalQuantity = 1; if ($product['id_product_attribute']) { $combination = $this->findProductCombinationById($product['id_product_attribute']); if ($combination['minimal_quantity']) { - $minimal_quantity = $combination['minimal_quantity']; + $minimalQuantity = (int) $combination['minimal_quantity']; } } else { - $minimal_quantity = $this->product->minimal_quantity; + $minimalQuantity = (int) $this->product->minimal_quantity; } - return $minimal_quantity; + if ($minimalQuantity < 1) { + $minimalQuantity = 1; + } + + return $minimalQuantity; } /** @@ -1294,22 +1329,62 @@ public function findProductCombinationById(int $combinationId) } /** + * Gets the minimal quantity the customer has to purchase. We cannot just let him buy 1 piece + * if the minimal quantity is higher. Also, we adjust it by the quantity already in cart. + * + * @todo This method should be migrated to ProductLazyArray, so it's available also in listings. + * It's already implemented there. + * * @param array $product * - * @return int + * @return int Minimal quantity of product the customer buy right now, always a positive integer */ - protected function getRequiredQuantity(array $product) + protected function getRequiredQuantity(ProductLazyArray|array $product) { - $requiredQuantity = (int) Tools::getValue('quantity_wanted', $this->getProductMinimalQuantity($product)); - if ($requiredQuantity < $product['minimal_quantity']) { - $requiredQuantity = $product['minimal_quantity']; + // For the required quantity, we will need to limit it by the minimal quantity on the low side. + $requiredQuantityForPurchase = $this->getProductMinimalQuantity($product); + + /* + * We reduce it by the quantity we already have in cart. If the user already has a sufficient + * quantity in the cart, we don't need to add more. Although it may seem that we can just reset + * the minimal quantity to one in that case, we must not do that, because the quantity in the cart + * may not be the correct one. + */ + if (!empty($product['cart_quantity'])) { + $requiredQuantityForPurchase -= $product['cart_quantity']; + if ($requiredQuantityForPurchase < 1) { + $requiredQuantityForPurchase = 1; + } } - if ($product['cart_quantity'] >= $requiredQuantity) { - return 0; + return $requiredQuantityForPurchase; + } + + /** + * Gets the quantity wanted by the customer for the product. We will take his request, + * but we will adjust it if it's lower than the required quantity. + * + * @todo This method should be migrated to ProductLazyArray, so it's available also in listings. + * It's already implemented there. + * + * @param array $product + * + * @return int Quantity of product requested by the customer, altered if needed, always a positive integer + */ + public function getWantedQuantity(ProductLazyArray|array $product): int + { + // Get the quantity wanted from the request + $quantityWantedByTheCustomer = (int) Tools::getValue('quantity_wanted', 1); + + // Get minimal required quantity for purchase + $requiredQuantityForPurchase = $this->getRequiredQuantity($product); + + // If the wanted quantity is lower than the required, we adjust it + if ($quantityWantedByTheCustomer < $requiredQuantityForPurchase) { + $quantityWantedByTheCustomer = $requiredQuantityForPurchase; } - return $requiredQuantity; + return $quantityWantedByTheCustomer; } /** diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0028e29091236..a4b0604eda890 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -510,6 +510,89 @@ Changelog for PrestaShop 9 - #40298: Functional tests - Fix create account in FO classic theme test (by @nesrineabdmouleh) - #39166: Refactor manufacturer behat tests (by @jolelievre) +#################################### +# v9.0.3 - (2026-01-22) +#################################### + +- Back Office: + - Improvement: + - #40517: Add some help boxes to product page (by @Hlavtox) + - #39923: Improve wording of some settings, better explain the meaning of them (by @Hlavtox) + - #40230: Adds help text to product page fields (by @Hlavtox) + - Bug fix: + - #40563: Admin API improvements for combination endpoints (by @jolelievre) + - #40556: Fix: CsvFileReader service fails with "You have requested a non-existent service 'session'" (by @Codencode) + - #38775: Fix: Multishop - error loading CMS pages removed from the default shop (by @Codencode) + - #40499: Fix: When saving an Attribute is_color_group is not updated. (by @Codencode) + - #40554: Fix: always display taxes total in order summary (by @Codencode) + - #40532: BO Product page, fix feature value collection indexes (by @jolelievre) + - #40433: Fix: Module update problem (by @Codencode) + - #40054: Use URL when building urls to prevent subtle mistakes with &? (by @tswfi) + - #40036: BO - Product : Fixed feature display in multishop (by @Progi1984) + - #39854: Fix: Quick Access links redirect to root instead of subdirectory, causing 404 (by @Codencode) + - #40050: Fix: Incorrect redirect from HTTP to HTTPS on the admin login page when PrestaShop is in a subfolder (by @Codencode) + - #40475: Fix link for redirection on country BO page (by @jolelievre) + - #40066: Fix: [BO] Admin Countries page redirect issue with multishop after changing shop (by @Codencode) + - #40329: Prevent NoResultException when checking for existing translations (by @ChillCode) + - #39926: Fix: handle SELECT fields without no_quotes in getSensitiveAttributes (by @Codencode) + - #40001: Fix redirect after editing root category to use current categoryId in stead of PS_HOME_CATEGORY (by @Codencode) + - #39869: Update monologger to v3 (by @NKoonen) + - #40256: Fix: Issue retrieving product price when adding the first specific_price (by @Codencode) + - #40243: Admin API handle position update (by @jolelievre) + - #40257: Prevent saving ajax URL for future login redirection, or the redirect… (by @jolelievre) + - #40112: Bump prestakit to v2.0.5 (by @Quetzacoalt91) + - Refactoring: + - #37667: Apply backoffice optimizations (by @Hlavtox) +- Front Office: + - New feature: + - #40403: Allow easily hooking into country and currency selection logic (by @Hlavtox) + - Improvement: + - #40537: Remove unnecessary force refresh in checkout (by @Hlavtox) + - #40248: Prevent Exposure of Sensitive Product Attributes in Front Office (by @M0rgan01) + - Bug fix: + - #40246: Fix preview in multilang (by @tleon) + - #39582: Fix: Product customization text field bug with using symbol {} (by @Codencode) + - #40117: Fix cart rule validation in front office (by @Hlavtox) + - #40262: Allow access to customized files preview without multi-lang enabled (by @kpodemski) + - #40137: Updated zxcvbn to a maintained version for consistency with backend checks (by @tleon) + - Refactoring: + - #40406: Comment how language setting works in FO (by @Hlavtox) +- Core: + - Improvement: + - #40269: Prevent database inconsistencies by preventing faulty group delete calls (by @Hlavtox) + - #40133: Update ca-bundle from 1.3.7 to 1.5.9 (by @tswfi) + - #40350: Remove the composer config to ignore audit (by @jolelievre) + - #40332: Restore original repository for ps_apiresources (by @nicosomb) + - #40312: Bump to `9.0.3` (by @boherm) + - #40134: Docker : Fixed Install of xdebug (by @Progi1984) + - Bug fix: + - #40585: Preliminary tasks for patch version 9.0.3 (by @jolelievre) + - #40479: Fix legacy profiler in the back office (by @kpodemski) + - #40562: Update VAT rates for Estonia and Romania (by @Codencode) + - #40496: Fix some type issues related to carriers (by @Hlavtox) + - #40423: Fix empty extra vars / product list when using the new automatic text email option (by @matrixino) + - #40040: Always request a non cached result in Order::getIdByCartId (by @ilsalvopss) + - #40400: Simplify cart rule minimal value by avoiding subtracting values (by @Hlavtox) + - Refactoring: + - #40389: Comment logic related to addresses and their initialization (by @Hlavtox) +- Installer: + - Bug fix: + - #40574: Fix Makefile to prevent build assets twice (by @jolelievre) + - #40077: Install Console : Allow characters "<" & ">" in admin password (by @Progi1984) + - #40114: Chore(Makefile): fix Makefile shell detection issue (by @tyloo) +- Localization: + - Bug fix: + - #40521: Fix default fixtures translation (by @jolelievre) +- Tests: + - Improvement: + - #40512: Functional Tests : Bump @prestashop-core/ui-testing (by @Progi1984) + - #40458: Functional Tests : Bump @prestashop-core/ui-testing (by @Progi1984) + - #40434: Functional Tests : Bump @prestashop-core/ui-testing (by @Progi1984) + - #40363: Functional Tests : Bump @prestashop-core/ui-testing (by @Progi1984) + - #40138: Functional Tests : Bump @prestashop-core/ui-testing (by @Progi1984) + - Refactoring: + - #40298: Functional tests - Fix create account in FO classic theme test (by @nesrineabdmouleh) + #################################### # v9.0.2 - (2025-12-01) #################################### diff --git a/install-dev/data/xml/hook.xml b/install-dev/data/xml/hook.xml index 19e1fd6d7dcce..69cfa5da19657 100644 --- a/install-dev/data/xml/hook.xml +++ b/install-dev/data/xml/hook.xml @@ -5638,5 +5638,30 @@ Action after initializing context currency Allows modules to modify the context currency after it has been initialized. + + actionFacetedSearchSetSupportedControllers + + <description/> + </hook> + <hook id="actionFacetedSearchFilters"> + <name>actionFacetedSearchFilters</name> + <title/> + <description/> + </hook> + <hook id="actionMainMenuModifier"> + <name>actionMainMenuModifier</name> + <title/> + <description/> + </hook> + <hook id="actionFacetedSearchCacheKeyGeneration"> + <name>actionFacetedSearchCacheKeyGeneration</name> + <title/> + <description/> + </hook> + <hook id="gSitemapAppendUrls"> + <name>gSitemapAppendUrls</name> + <title/> + <description/> + </hook> </entities> </entity_hook> diff --git a/localization/at.xml b/localization/at.xml index bddb55d99d1d0..08d288a829bfa 100644 --- a/localization/at.xml +++ b/localization/at.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/be.xml b/localization/be.xml index af8eaf8eef586..0c8f73aeea99c 100644 --- a/localization/be.xml +++ b/localization/be.xml @@ -18,7 +18,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -36,7 +36,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/bg.xml b/localization/bg.xml index f21a4792b7b9b..ba5eb11e6fcbb 100644 --- a/localization/bg.xml +++ b/localization/bg.xml @@ -16,7 +16,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/cy.xml b/localization/cy.xml index 6c47114287fb3..24229872e562d 100644 --- a/localization/cy.xml +++ b/localization/cy.xml @@ -17,7 +17,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/cz.xml b/localization/cz.xml index 013465de2d293..f3e2437a60407 100644 --- a/localization/cz.xml +++ b/localization/cz.xml @@ -15,7 +15,7 @@ <tax id="6" name="ΦΠΑ CY 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="7" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="9" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="9" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -33,7 +33,7 @@ <tax id="24" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="27" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="27" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/de.xml b/localization/de.xml index 79b0869791e83..99311233fba80 100644 --- a/localization/de.xml +++ b/localization/de.xml @@ -15,7 +15,7 @@ <tax id="6" name="ΦΠΑ CY 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="9" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="9" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -33,7 +33,7 @@ <tax id="24" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="27" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="27" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/dk.xml b/localization/dk.xml index 86eb42805bb2f..57e37c4878dbf 100644 --- a/localization/dk.xml +++ b/localization/dk.xml @@ -14,7 +14,7 @@ <tax id="5" name="ΦΠΑ CY 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="6" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="7" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="8" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="8" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -32,7 +32,7 @@ <tax id="23" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="24" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="26" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="26" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/ee.xml b/localization/ee.xml index dd6da169f1227..3f7ffa8f02d2b 100644 --- a/localization/ee.xml +++ b/localization/ee.xml @@ -7,7 +7,7 @@ <language iso_code="et"/> </languages> <taxes> - <tax id="1" name="km EE 20%" rate="20" eu-tax-group="virtual"/> + <tax id="1" name="km EE 24%" rate="24" eu-tax-group="virtual"/> <tax id="2" name="km EE 9%" rate="9"/> <tax id="3" name="USt. AT 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="4" name="TVA BE 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> @@ -33,7 +33,7 @@ <tax id="24" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="27" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="27" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/es.xml b/localization/es.xml index b92ed8b9b9c49..bbd1ab2120b11 100644 --- a/localization/es.xml +++ b/localization/es.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="VAT UK 20%" rate="20.0" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/fi.xml b/localization/fi.xml index e773a9199fd71..38a7ce834dfce 100644 --- a/localization/fi.xml +++ b/localization/fi.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="VAT UK 20%" rate="20.0" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/fr.xml b/localization/fr.xml index c6116bec6605b..1eb9498f49473 100644 --- a/localization/fr.xml +++ b/localization/fr.xml @@ -27,7 +27,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="VAT UK 20%" rate="20.0" auto-generated="1" from-eu-tax-group="virtual"/> @@ -44,7 +44,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/gb.xml b/localization/gb.xml index d4a400197ac0b..306e7dfbe3609 100644 --- a/localization/gb.xml +++ b/localization/gb.xml @@ -16,7 +16,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -33,7 +33,7 @@ <tax id="24" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="27" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="27" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/gr.xml b/localization/gr.xml index 95c4e7205fc8f..290d8edc30a7f 100644 --- a/localization/gr.xml +++ b/localization/gr.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/hr.xml b/localization/hr.xml index 48bebe4e8257f..2ca3218f35f0b 100644 --- a/localization/hr.xml +++ b/localization/hr.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/hu.xml b/localization/hu.xml index 289c8664eaafe..d7117a1f4a329 100644 --- a/localization/hu.xml +++ b/localization/hu.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/ie.xml b/localization/ie.xml index 9a312508f6509..866f0ea137ea2 100644 --- a/localization/ie.xml +++ b/localization/ie.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/it.xml b/localization/it.xml index 8aa930b098883..d6d6bb20593de 100644 --- a/localization/it.xml +++ b/localization/it.xml @@ -19,7 +19,7 @@ <tax id="10" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="13" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="13" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="16" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -36,7 +36,7 @@ <tax id="27" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="30" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="30" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="33" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/lt.xml b/localization/lt.xml index d4a3093ac826f..1eac5bed69ff5 100644 --- a/localization/lt.xml +++ b/localization/lt.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/lu.xml b/localization/lu.xml index 439865a7152dd..7067c5a8c7da4 100644 --- a/localization/lu.xml +++ b/localization/lu.xml @@ -19,7 +19,7 @@ <tax id="10" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="13" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="13" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="16" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -36,7 +36,7 @@ <tax id="27" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="30" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="30" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="33" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/lv.xml b/localization/lv.xml index f31ce948c01ee..5d523284bf355 100644 --- a/localization/lv.xml +++ b/localization/lv.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/mc.xml b/localization/mc.xml index 3cec58a64764d..e029d66825d43 100644 --- a/localization/mc.xml +++ b/localization/mc.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/mt.xml b/localization/mt.xml index 020fe41a97f4a..25d91193fa1a5 100644 --- a/localization/mt.xml +++ b/localization/mt.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/nl.xml b/localization/nl.xml index 048117e70846f..e2373b25a0416 100644 --- a/localization/nl.xml +++ b/localization/nl.xml @@ -16,7 +16,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -33,7 +33,7 @@ <tax id="24" name="VAT MT 18%" rate="18" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="25" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="27" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="27" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/pl.xml b/localization/pl.xml index 39c6913b9b802..b6e2032308a79 100644 --- a/localization/pl.xml +++ b/localization/pl.xml @@ -18,7 +18,7 @@ <tax id="11" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="14" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="14" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="16" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="17" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="28" name="VAT MT 18%" rate="18" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="31" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="31" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="33" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="34" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/pt.xml b/localization/pt.xml index 1b23812edfa02..5e6bca8e92ac6 100644 --- a/localization/pt.xml +++ b/localization/pt.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="VAT MT 18%" rate="18" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/ro.xml b/localization/ro.xml index 94c218288d0d6..ef4633b3730de 100644 --- a/localization/ro.xml +++ b/localization/ro.xml @@ -7,7 +7,7 @@ <language iso_code="ro"/> </languages> <taxes> - <tax id="1" name="TVA RO 19%" rate="19" eu-tax-group="virtual"/> + <tax id="1" name="TVA RO 21%" rate="21" eu-tax-group="virtual"/> <tax id="2" name="TVA RO 9%" rate="9"/> <tax id="3" name="TVA RO 5%" rate="5"/> <tax id="4" name="TVA RO 0%" rate="0"/> @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> diff --git a/localization/se.xml b/localization/se.xml index 76c2be015b7f6..4c67f75be4662 100644 --- a/localization/se.xml +++ b/localization/se.xml @@ -18,7 +18,7 @@ <tax id="9" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="12" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="12" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="15" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -36,7 +36,7 @@ <tax id="27" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="30" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="30" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="32" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <taxRulesGroup name="SE Standard Rate (25%)"> diff --git a/localization/si.xml b/localization/si.xml index 61e76b6d83741..2131efc4c8d9e 100644 --- a/localization/si.xml +++ b/localization/si.xml @@ -16,7 +16,7 @@ <tax id="7" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="8" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="10" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="10" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="11" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -34,7 +34,7 @@ <tax id="25" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="26" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="28" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="28" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="29" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="DPH SK 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <taxRulesGroup name="SI Standard Rate (22%)"> diff --git a/localization/sk.xml b/localization/sk.xml index ef0f82f1d749d..0fbd32040d69a 100644 --- a/localization/sk.xml +++ b/localization/sk.xml @@ -17,7 +17,7 @@ <tax id="8" name="DPH CZ 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="9" name="MwSt. DE 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="10" name="moms DK 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="11" name="km EE 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="11" name="km EE 24%" rate="24" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="12" name="IVA ES 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="13" name="ALV FI 25.5%" rate="25.5" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="14" name="TVA FR 20%" rate="20" auto-generated="1" from-eu-tax-group="virtual"/> @@ -35,7 +35,7 @@ <tax id="26" name="BTW NL 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="27" name="PTU PL 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="28" name="IVA PT 23%" rate="23" auto-generated="1" from-eu-tax-group="virtual"/> - <tax id="29" name="TVA RO 19%" rate="19" auto-generated="1" from-eu-tax-group="virtual"/> + <tax id="29" name="TVA RO 21%" rate="21" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="30" name="Moms SE 25%" rate="25" auto-generated="1" from-eu-tax-group="virtual"/> <tax id="31" name="DDV SI 22%" rate="22" auto-generated="1" from-eu-tax-group="virtual"/> <taxRulesGroup name="SK Standard Rate (23%)"> diff --git a/src/Adapter/Debug/DebugMode.php b/src/Adapter/Debug/DebugMode.php index f199043a0dc4a..8f574c3814f77 100644 --- a/src/Adapter/Debug/DebugMode.php +++ b/src/Adapter/Debug/DebugMode.php @@ -221,7 +221,11 @@ public function changePsModeDevValue($value) { // Check custom defines file first if ($this->isCustomDefinesReadable()) { - return $this->updateDebugModeValueInCustomFile($value); + $result = $this->updateDebugModeValueInCustomFile($value); + // If the constant is not found in custom file, fallback to main file + if ($result !== self::DEBUG_MODE_ERROR_NO_DEFINITION_FOUND) { + return $result; + } } if ($this->isMainDefinesReadable()) { diff --git a/src/Adapter/Debug/DebugProfiling.php b/src/Adapter/Debug/DebugProfiling.php index cea5254a9f795..a74e84fa0dbc1 100644 --- a/src/Adapter/Debug/DebugProfiling.php +++ b/src/Adapter/Debug/DebugProfiling.php @@ -175,7 +175,11 @@ private function changeProfilingValue(string $value): int { // Check custom defines file first if ($this->isCustomDefinesReadable()) { - return $this->updateProfilingValueInCustomFile($value); + $result = $this->updateProfilingValueInCustomFile($value); + // If the constant is not found in custom file, fallback to main file + if ($result !== self::DEBUG_PROFILING_ERROR_NO_DEFINITION_FOUND) { + return $result; + } } if ($this->isMainDefinesReadable()) { diff --git a/src/Adapter/Discount/QueryHandler/GetDiscountTypesHandler.php b/src/Adapter/Discount/QueryHandler/GetDiscountTypesHandler.php new file mode 100644 index 0000000000000..f2c184e4df092 --- /dev/null +++ b/src/Adapter/Discount/QueryHandler/GetDiscountTypesHandler.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright since 2007 PrestaShop SA and Contributors + * PrestaShop is an International Registered Trademark & Property of PrestaShop SA + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.md. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to https://devdocs.prestashop.com/ for more information. + * + * @author PrestaShop SA and Contributors <contact@prestashop.com> + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +namespace PrestaShop\PrestaShop\Adapter\Discount\QueryHandler; + +use PrestaShop\PrestaShop\Adapter\Discount\Repository\DiscountTypeRepository; +use PrestaShop\PrestaShop\Core\CommandBus\Attributes\AsQueryHandler; +use PrestaShop\PrestaShop\Core\Domain\Discount\Query\GetDiscountTypes; +use PrestaShop\PrestaShop\Core\Domain\Discount\QueryHandler\GetDiscountTypesHandlerInterface; +use PrestaShop\PrestaShop\Core\Domain\Discount\QueryResult\DiscountType; + +#[AsQueryHandler] +class GetDiscountTypesHandler implements GetDiscountTypesHandlerInterface +{ + public function __construct( + private readonly DiscountTypeRepository $discountTypeRepository, + ) { + } + + /** + * @return DiscountType[] + */ + public function handle(GetDiscountTypes $query): array + { + $groupedTypes = $this->discountTypeRepository->getAllTypes(); + + return array_map( + fn (array $type) => new DiscountType( + $type['id_cart_rule_type'], + $type['discount_type'], + $type['names'], + $type['descriptions'], + $type['is_core'], + $type['enabled'] + ), + array_values($groupedTypes) + ); + } +} diff --git a/src/Adapter/Discount/Repository/DiscountTypeRepository.php b/src/Adapter/Discount/Repository/DiscountTypeRepository.php index fc7856007e852..63b32eaec22a3 100644 --- a/src/Adapter/Discount/Repository/DiscountTypeRepository.php +++ b/src/Adapter/Discount/Repository/DiscountTypeRepository.php @@ -40,6 +40,52 @@ public function __construct( ) { } + /** + * Get all discount types grouped by discount type ID with translations + * + * @return array<int, array{id_cart_rule_type: int, discount_type: string, is_core: bool, enabled: bool, names: array<int, string>, descriptions: array<int, string>}> + */ + public function getAllTypes(): array + { + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('crt.id_cart_rule_type', 'crt.discount_type', 'crt.is_core', 'crt.active', 'crtl.name', 'crtl.description', 'crtl.id_lang') + ->from($this->dbPrefix . 'cart_rule_type', 'crt') + ->leftJoin('crt', $this->dbPrefix . 'cart_rule_type_lang', 'crtl', 'crt.id_cart_rule_type = crtl.id_cart_rule_type') + ->orderBy('crt.id_cart_rule_type', 'ASC') + ->addOrderBy('crtl.id_lang', 'ASC') + ; + + $allTypes = $qb->executeQuery()->fetchAllAssociative(); + $groupedTypes = []; + + foreach ($allTypes as $type) { + $discountTypeId = (int) $type['id_cart_rule_type']; + $langId = !empty($type['id_lang']) ? (int) $type['id_lang'] : null; + + if (!isset($groupedTypes[$discountTypeId])) { + $groupedTypes[$discountTypeId] = [ + 'id_cart_rule_type' => $discountTypeId, + 'discount_type' => $type['discount_type'], + 'is_core' => (bool) $type['is_core'], + 'enabled' => (bool) $type['active'], + 'names' => [], + 'descriptions' => [], + ]; + } + + // Add translations if available + if ($langId !== null && !empty($type['name'])) { + $groupedTypes[$discountTypeId]['names'][$langId] = $type['name']; + } + if ($langId !== null && !empty($type['description'])) { + $groupedTypes[$discountTypeId]['descriptions'][$langId] = $type['description']; + } + } + + return $groupedTypes; + } + /** * Get all active discount types * diff --git a/src/Adapter/Discount/Validate/DiscountValidator.php b/src/Adapter/Discount/Validate/DiscountValidator.php index 6eb3fa63688dc..b47c54c357a38 100644 --- a/src/Adapter/Discount/Validate/DiscountValidator.php +++ b/src/Adapter/Discount/Validate/DiscountValidator.php @@ -28,6 +28,7 @@ namespace PrestaShop\PrestaShop\Adapter\Discount\Validate; use CartRule; +use Customer; use PrestaShop\Decimal\DecimalNumber; use PrestaShop\PrestaShop\Adapter\AbstractObjectModelValidator; use PrestaShop\PrestaShop\Adapter\Attribute\Repository\AttributeRepository; @@ -96,6 +97,7 @@ public function setDiscountRepository(DiscountRepository $discountRepository): v public function validate(CartRule $cartRule): void { $this->validateCartRuleProperty($cartRule, 'id_customer', DiscountConstraintException::INVALID_CUSTOMER_ID); + $this->assertCustomerIsNotGuest($cartRule); $this->validateCartRuleProperty($cartRule, 'date_from', DiscountConstraintException::INVALID_DATE_FROM); $this->validateCartRuleProperty($cartRule, 'date_to', DiscountConstraintException::INVALID_DATE_TO); $this->validateCartRuleProperty($cartRule, 'description', DiscountConstraintException::INVALID_DESCRIPTION); @@ -318,4 +320,19 @@ private function assertDateRangeIsCorrect(CartRule $cartrule): void throw new DiscountConstraintException('Date from cannot be greater than date to.', DiscountConstraintException::DATE_FROM_GREATER_THAN_DATE_TO); } } + + private function assertCustomerIsNotGuest(CartRule $cartRule): void + { + if (empty($cartRule->id_customer)) { + return; + } + + $customer = new Customer((int) $cartRule->id_customer); + if ($customer->isGuest()) { + throw new DiscountConstraintException( + sprintf('Cannot assign discount to guest customer with ID %d', $cartRule->id_customer), + DiscountConstraintException::INVALID_GUEST_CUSTOMER + ); + } + } } diff --git a/src/Adapter/Presenter/Product/ProductLazyArray.php b/src/Adapter/Presenter/Product/ProductLazyArray.php index 384d8b210d493..286922a8090f1 100644 --- a/src/Adapter/Presenter/Product/ProductLazyArray.php +++ b/src/Adapter/Presenter/Product/ProductLazyArray.php @@ -1199,12 +1199,8 @@ protected function shouldEnableAddToCartButton( } // Disable because of stock management - if ( - $settings->stock_management_enabled - && !$product['allow_oosp'] - && ($product['quantity'] <= 0 - || $product['quantity'] - $this->getQuantityWanted() < 0 - || $product['quantity'] - $this->getMinimalQuantity() < 0) + if ($settings->stock_management_enabled && !$product['allow_oosp'] + && ($product['quantity'] <= 0 || $product['quantity'] - $this->getQuantityWanted() < 0) ) { $shouldEnable = false; } @@ -1213,22 +1209,77 @@ protected function shouldEnableAddToCartButton( } /** - * @return int Quantity of product requested by the customer + * Gets the quantity wanted by the customer for the product. We will take his request, + * but we will adjust it if it's lower than the required quantity. + * + * @return int Quantity of product requested by the customer, altered if needed, always a positive integer */ - private function getQuantityWanted() + #[LazyArrayAttribute(arrayAccess: true)] + public function getQuantityWanted() { - return (int) Tools::getValue( - 'quantity_wanted', - $this->product['quantity_wanted'] ?? 1 - ); + if (empty($this->product['quantity_wanted'])) { + // Get the quantity wanted from the request + $quantityWantedByTheCustomer = (int) Tools::getValue('quantity_wanted', 1); + + // Get minimal required quantity for purchase + $requiredQuantityForPurchase = $this->getQuantityRequired(); + + if ($quantityWantedByTheCustomer < $requiredQuantityForPurchase) { + $quantityWantedByTheCustomer = $requiredQuantityForPurchase; + } + + $this->product['quantity_wanted'] = $quantityWantedByTheCustomer; + } + + return $this->product['quantity_wanted']; } /** - * @return int Minimal quantity of product requested by the customer + * Gets the minimal quantity the customer has to purchase. We cannot just let him buy 1 piece + * if the minimal quantity is higher. Also, we adjust it by the quantity already in cart. + * + * @return int Minimal quantity of product the customer buy right now, always a positive integer */ - private function getMinimalQuantity() + #[LazyArrayAttribute(arrayAccess: true)] + public function getQuantityRequired() { - return (int) $this->product['minimal_quantity']; + // For the required quantity, we will need to limit it by the minimal quantity on the low side. + $requiredQuantityForPurchase = $this->getMinimalQuantity(); + + /* + * We reduce it by the quantity we already have in cart. If the user already has a sufficient + * quantity in the cart, we don't need to add more. Although it may seem that we can just reset + * the minimal quantity to one in that case, we must not do that, because the quantity in the cart + * may not be the correct one. + */ + if (!empty($this->product['cart_quantity'])) { + $requiredQuantityForPurchase -= $this->product['cart_quantity']; + if ($requiredQuantityForPurchase < 1) { + $requiredQuantityForPurchase = 1; + } + } + + return $requiredQuantityForPurchase; + } + + /** + * Gets the minimal quantity allowed for the product or its combination. With no adjustments + * by the current context. The builder of this object is responsible for passing the correct + * minimal quantity depending on the combination selected. + * + * @return int Minimal quantity of product from it's settings, always a positive integer + */ + #[LazyArrayAttribute(arrayAccess: true)] + public function getMinimalQuantity() + { + $minimalQuantity = (int) $this->product['minimal_quantity']; + + // If we received faulty data, we correct it to 1 + if ($minimalQuantity < 1) { + $minimalQuantity = 1; + } + + return $minimalQuantity; } /** diff --git a/src/Core/Domain/Discount/Exception/DiscountConstraintException.php b/src/Core/Domain/Discount/Exception/DiscountConstraintException.php index 0ba9f77a85bda..cd862a948f532 100644 --- a/src/Core/Domain/Discount/Exception/DiscountConstraintException.php +++ b/src/Core/Domain/Discount/Exception/DiscountConstraintException.php @@ -78,4 +78,5 @@ class DiscountConstraintException extends DiscountException public const INVALID_PRODUCT_DISCOUNT_MISSING_TARGET = 48; public const INVALID_PRODUCT_DISCOUNT_INCOMPATIBLE_TARGETS = 49; public const INVALID_PRODUCT_DISCOUNT_INCOMPATIBLE_REDUCTIONS = 50; + public const INVALID_GUEST_CUSTOMER = 51; } diff --git a/src/Core/Domain/Discount/Query/GetDiscountTypes.php b/src/Core/Domain/Discount/Query/GetDiscountTypes.php new file mode 100644 index 0000000000000..472e4a8528f9b --- /dev/null +++ b/src/Core/Domain/Discount/Query/GetDiscountTypes.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright since 2007 PrestaShop SA and Contributors + * PrestaShop is an International Registered Trademark & Property of PrestaShop SA + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.md. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to https://devdocs.prestashop.com/ for more information. + * + * @author PrestaShop SA and Contributors <contact@prestashop.com> + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +namespace PrestaShop\PrestaShop\Core\Domain\Discount\Query; + +class GetDiscountTypes +{ +} diff --git a/src/Core/Domain/Discount/QueryHandler/GetDiscountTypesHandlerInterface.php b/src/Core/Domain/Discount/QueryHandler/GetDiscountTypesHandlerInterface.php new file mode 100644 index 0000000000000..e2cca3a665c57 --- /dev/null +++ b/src/Core/Domain/Discount/QueryHandler/GetDiscountTypesHandlerInterface.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright since 2007 PrestaShop SA and Contributors + * PrestaShop is an International Registered Trademark & Property of PrestaShop SA + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.md. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to https://devdocs.prestashop.com/ for more information. + * + * @author PrestaShop SA and Contributors <contact@prestashop.com> + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +namespace PrestaShop\PrestaShop\Core\Domain\Discount\QueryHandler; + +use PrestaShop\PrestaShop\Core\Domain\Discount\Query\GetDiscountTypes; +use PrestaShop\PrestaShop\Core\Domain\Discount\QueryResult\DiscountType; + +interface GetDiscountTypesHandlerInterface +{ + /** + * @return DiscountType[] + */ + public function handle(GetDiscountTypes $query): array; +} diff --git a/src/Core/Domain/Discount/QueryResult/DiscountType.php b/src/Core/Domain/Discount/QueryResult/DiscountType.php new file mode 100644 index 0000000000000..df4470f224660 --- /dev/null +++ b/src/Core/Domain/Discount/QueryResult/DiscountType.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright since 2007 PrestaShop SA and Contributors + * PrestaShop is an International Registered Trademark & Property of PrestaShop SA + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.md. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to https://devdocs.prestashop.com/ for more information. + * + * @author PrestaShop SA and Contributors <contact@prestashop.com> + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +namespace PrestaShop\PrestaShop\Core\Domain\Discount\QueryResult; + +class DiscountType +{ + /** + * @param int $discountTypeId + * @param string $type + * @param array<int, string> $localizedNames indexed by language ID + * @param array<int, string> $localizedDescriptions indexed by language ID + * @param bool $isCore + * @param bool $enabled + */ + public function __construct( + private readonly int $discountTypeId, + private readonly string $type, + private readonly array $localizedNames, + private readonly array $localizedDescriptions, + private readonly bool $isCore = false, + private readonly bool $enabled = true + ) { + } + + public function getDiscountTypeId(): int + { + return $this->discountTypeId; + } + + public function getType(): string + { + return $this->type; + } + + public function getLocalizedNames(): array + { + return $this->localizedNames; + } + + public function getLocalizedDescriptions(): array + { + return $this->localizedDescriptions; + } + + public function isCore(): bool + { + return $this->isCore; + } + + public function isEnabled(): bool + { + return $this->enabled; + } +} diff --git a/src/PrestaShopBundle/Resources/config/services/adapter/discount.yml b/src/PrestaShopBundle/Resources/config/services/adapter/discount.yml index 913d739603617..3b5233fbae96c 100644 --- a/src/PrestaShopBundle/Resources/config/services/adapter/discount.yml +++ b/src/PrestaShopBundle/Resources/config/services/adapter/discount.yml @@ -40,6 +40,9 @@ services: PrestaShop\PrestaShop\Adapter\Discount\QueryHandler\GetDiscountForEditingHandler: autoconfigure: true + PrestaShop\PrestaShop\Adapter\Discount\QueryHandler\GetDiscountTypesHandler: + autoconfigure: true + PrestaShop\PrestaShop\Adapter\Discount\Validate\DiscountValidator: calls: - setDiscountRepository: [ '@PrestaShop\PrestaShop\Adapter\Discount\Repository\DiscountRepository' ] diff --git a/tests/Integration/Adapter/Presenter/Product/ProductLazyArrayTest.php b/tests/Integration/Adapter/Presenter/Product/ProductLazyArrayTest.php index 9d6ae9592989e..eeea34c2d872e 100644 --- a/tests/Integration/Adapter/Presenter/Product/ProductLazyArrayTest.php +++ b/tests/Integration/Adapter/Presenter/Product/ProductLazyArrayTest.php @@ -94,6 +94,7 @@ class ProductLazyArrayTest extends TestCase 'out_of_stock' => OutOfStockType::OUT_OF_STOCK_DEFAULT, 'customizable' => 0, 'active' => 1, + 'minimal_quantity' => 1, ]; private const PRODUCT_DISCONTINUED = 'This product is no longer available for sale.'; diff --git a/tests/Integration/Behaviour/Features/Context/CustomerFeatureContext.php b/tests/Integration/Behaviour/Features/Context/CustomerFeatureContext.php index fdf79d4d05264..ef997c08d0a00 100644 --- a/tests/Integration/Behaviour/Features/Context/CustomerFeatureContext.php +++ b/tests/Integration/Behaviour/Features/Context/CustomerFeatureContext.php @@ -65,6 +65,26 @@ public function createCustomer($customerName, $customerEmail) SharedStorage::getStorage()->set($customerName, $customer->id); } + /** + * @Given /^there is a guest customer named "(.+)" whose email is "(.+)"$/ + */ + public function createGuestCustomer($customerName, $customerEmail) + { + /** @var Hashing $crypto */ + $crypto = ServiceLocator::get(Hashing::class); + + $customer = new Customer(); + $customer->firstname = 'fake'; + $customer->lastname = 'fake'; + $customer->passwd = $crypto->hash('Correct Horse Battery Staple'); + $customer->email = $customerEmail; + $customer->is_guest = true; + $customer->id_shop = Context::getContext()->shop->id; + $customer->add(); + $this->customers[$customerName] = $customer; + SharedStorage::getStorage()->set($customerName, $customer->id); + } + /** * @Given /^customer "(.+)" belongs to group "(.+)"$/ */ diff --git a/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountFeatureContext.php b/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountFeatureContext.php index 2e4aa6235c7ee..3c89d3cc8e64f 100644 --- a/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountFeatureContext.php +++ b/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountFeatureContext.php @@ -136,6 +136,14 @@ public function assertDiscountIncompatibleReductions(): void $this->assertLastErrorIs(DiscountConstraintException::class, DiscountConstraintException::INVALID_PRODUCT_DISCOUNT_INCOMPATIBLE_REDUCTIONS); } + /** + * @Then I should get an error that discount cannot be assigned to guest customers + */ + public function assertDiscountCannotBeAssignedToGuestCustomers(): void + { + $this->assertLastErrorIs(DiscountConstraintException::class, DiscountConstraintException::INVALID_GUEST_CUSTOMER); + } + /** * @Then discount :discountReference should have the following properties: * diff --git a/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountTypesFeatureContext.php b/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountTypesFeatureContext.php new file mode 100644 index 0000000000000..366f4267b3313 --- /dev/null +++ b/tests/Integration/Behaviour/Features/Context/Domain/Discount/DiscountTypesFeatureContext.php @@ -0,0 +1,121 @@ +<?php +/** + * Copyright since 2007 PrestaShop SA and Contributors + * PrestaShop is an International Registered Trademark & Property of PrestaShop SA + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.md. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to https://devdocs.prestashop.com/ for more information. + * + * @author PrestaShop SA and Contributors <contact@prestashop.com> + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +namespace Tests\Integration\Behaviour\Features\Context\Domain\Discount; + +use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; +use PrestaShop\PrestaShop\Core\Domain\Discount\Query\GetDiscountTypes; +use RuntimeException; +use Tests\Integration\Behaviour\Features\Context\Domain\AbstractDomainFeatureContext; + +class DiscountTypesFeatureContext extends AbstractDomainFeatureContext +{ + /** + * @Then I should receive the following discount types: + * + * @param TableNode $table + */ + public function assertDiscountTypes(TableNode $table): void + { + $queryBus = $this->getQueryBus(); + $query = new GetDiscountTypes(); + $discountTypes = $queryBus->handle($query); + + Assert::assertNotNull($discountTypes, 'No discount types received'); + Assert::assertIsArray($discountTypes, 'Discount types should be an array'); + + $expectedDiscountTypes = $this->localizeByColumns($table); + + Assert::assertGreaterThanOrEqual( + count($expectedDiscountTypes), + count($discountTypes), + sprintf('Expected %d discount types but got %d', count($expectedDiscountTypes), count($discountTypes)) + ); + + foreach ($expectedDiscountTypes as $expectedDiscountType) { + $foundDiscountType = null; + foreach ($discountTypes as $discountType) { + if ($discountType->getType() === $expectedDiscountType['type']) { + $foundDiscountType = $discountType; + break; + } + } + + if (null === $foundDiscountType) { + throw new RuntimeException(sprintf('Couldnt find discount type "%s"', $expectedDiscountType['type'])); + } + + if (isset($expectedDiscountType['discountTypeId'])) { + Assert::assertEquals( + (int) $expectedDiscountType['discountTypeId'], + $foundDiscountType->getDiscountTypeId(), + sprintf('Unexpected discountTypeId for type "%s"', $expectedDiscountType['type']) + ); + } + + if (isset($expectedDiscountType['core'])) { + $expectedCore = filter_var($expectedDiscountType['core'], FILTER_VALIDATE_BOOLEAN); + Assert::assertEquals( + $expectedCore, + $foundDiscountType->isCore(), + sprintf('Unexpected core value for type "%s"', $expectedDiscountType['type']) + ); + } + + if (isset($expectedDiscountType['enabled'])) { + $expectedEnabled = filter_var($expectedDiscountType['enabled'], FILTER_VALIDATE_BOOLEAN); + Assert::assertEquals( + $expectedEnabled, + $foundDiscountType->isEnabled(), + sprintf('Unexpected enabled value for type "%s"', $expectedDiscountType['type']) + ); + } + + if (isset($expectedDiscountType['names'])) { + $actualNames = $foundDiscountType->getLocalizedNames(); + foreach ($expectedDiscountType['names'] as $langId => $expectedName) { + Assert::assertEquals( + $expectedName, + $actualNames[$langId], + sprintf('Unexpected name for language ID %d in type "%s"', $langId, $expectedDiscountType['type']) + ); + } + } + + if (isset($expectedDiscountType['descriptions'])) { + $actualDescriptions = $foundDiscountType->getLocalizedDescriptions(); + foreach ($expectedDiscountType['descriptions'] as $langId => $expectedDescription) { + Assert::assertEquals( + $expectedDescription, + $actualDescriptions[$langId], + sprintf('Unexpected description for language ID %d in type "%s"', $langId, $expectedDiscountType['type']) + ); + } + } + } + } +} diff --git a/tests/Integration/Behaviour/Features/Scenario/Discount/BO/add_discount_excludes_guest_customers.feature b/tests/Integration/Behaviour/Features/Scenario/Discount/BO/add_discount_excludes_guest_customers.feature new file mode 100644 index 0000000000000..7b009a8d1317a --- /dev/null +++ b/tests/Integration/Behaviour/Features/Scenario/Discount/BO/add_discount_excludes_guest_customers.feature @@ -0,0 +1,55 @@ +# ./vendor/bin/behat -c tests/Integration/Behaviour/behat.yml -s discount --tags add-discount-excludes-guests +@restore-all-tables-before-feature +@restore-languages-after-feature +@add-discount-excludes-guests +Feature: Add discount with single customer eligibility excludes guest customers + PrestaShop should prevent BO users from creating discounts for guest customers + As a BO user + I should not be able to create discounts that are assigned to guest customers + Guest customers should be excluded from the customer search when creating discounts + + Background: + Given shop "shop1" with name "test_shop" exists + Given there is a currency named "usd" with iso code "USD" and exchange rate of 0.92 + Given currency "usd" is the default one + And language with iso code "en" is the default one + And language "french" with locale "fr-FR" exists + Given there is a customer named "john_doe" whose email is "john.doe@example.com" + And there is a guest customer named "guest_customer" whose email is "guest@example.com" + + Scenario: Cannot create a discount limited to a guest customer + When I create a "cart_level" discount "discount_for_guest" with following properties: + | name[en-US] | Guest Discount | + | name[fr-FR] | Réduction Invité | + | active | true | + | valid_from | 2025-01-01 00:00:00 | + | valid_to | 2025-12-31 23:59:59 | + | code | GUEST_2025 | + | reduction_percent | 20.0 | + | customer | guest_customer | + | total_quantity | 100 | + | quantity_per_user | 1 | + | minimum_product_quantity | 0 | + Then I should get an error that discount cannot be assigned to guest customers + + Scenario: Can create a discount for a regular customer but not for a guest + When I create a "cart_level" discount "discount_for_regular" with following properties: + | name[en-US] | Regular Customer Discount | + | name[fr-FR] | Réduction Client | + | active | true | + | valid_from | 2025-01-01 00:00:00 | + | valid_to | 2025-12-31 23:59:59 | + | code | REGULAR_2025 | + | reduction_percent | 15.0 | + | customer | john_doe | + | total_quantity | 100 | + | quantity_per_user | 1 | + | minimum_product_quantity | 0 | + Then discount "discount_for_regular" should have the following properties: + | name[en-US] | Regular Customer Discount | + | name[fr-FR] | Réduction Client | + | customer | john_doe | + # This should fail if we try to update to guest customer + When I update discount "discount_for_regular" with the following properties: + | customer | guest_customer | + Then I should get an error that discount cannot be assigned to guest customers diff --git a/tests/Integration/Behaviour/Features/Scenario/Discount/BO/discount_types.feature b/tests/Integration/Behaviour/Features/Scenario/Discount/BO/discount_types.feature new file mode 100644 index 0000000000000..845d5ee59a35f --- /dev/null +++ b/tests/Integration/Behaviour/Features/Scenario/Discount/BO/discount_types.feature @@ -0,0 +1,18 @@ +# ./vendor/bin/behat -c tests/Integration/Behaviour/behat.yml -s discount --tags discount-types +@discount-types +Feature: Discount Types + PrestaShop provides discount types + As a developer + I must be able to retrieve the list of available discount types + + Background: + Given I enable feature flag "discount" + + Scenario: List all discount types + Then I should receive the following discount types: + | type | core | enabled | names[en-US] | descriptions[en-US] | + | cart_level | true | true | On cart amount | Discount applied to cart | + | product_level | true | true | On catalog products | Discount applied to specific products | + | free_shipping | true | true | On free shipping | Discount that provides free shipping to the order | + | free_gift | true | true | On free gift | Discount that provides a free gift product | + | order_level | true | true | On total order | Discount applied to the order | diff --git a/tests/Integration/Behaviour/behat.yml b/tests/Integration/Behaviour/behat.yml index d3673cef112e8..86ae0b80742dd 100644 --- a/tests/Integration/Behaviour/behat.yml +++ b/tests/Integration/Behaviour/behat.yml @@ -322,6 +322,7 @@ default: - Tests\Integration\Behaviour\Features\Context\Domain\CustomerFeatureContext - Tests\Integration\Behaviour\Features\Context\Domain\CustomerGroupFeatureContext - Tests\Integration\Behaviour\Features\Context\Domain\Discount\DiscountFeatureContext + - Tests\Integration\Behaviour\Features\Context\Domain\Discount\DiscountTypesFeatureContext - Tests\Integration\Behaviour\Features\Context\Domain\ProductFeatureContext - Tests\Integration\Behaviour\Features\Context\Domain\Product\AddProductFeatureContext - Tests\Integration\Behaviour\Features\Context\Domain\Product\Combination\CombinationAssertionFeatureContext diff --git a/tests/UI/campaigns/functional/API/02_checkEndpoints.ts b/tests/UI/campaigns/functional/API/02_checkEndpoints.ts index 8f226ef627dd3..5834997582ddb 100644 --- a/tests/UI/campaigns/functional/API/02_checkEndpoints.ts +++ b/tests/UI/campaigns/functional/API/02_checkEndpoints.ts @@ -204,6 +204,8 @@ describe('API : Check endpoints', async () => { // @todo: add tests '/customers: POST', // @todo: add tests + '/discount-types: GET', + // @todo: add tests '/discounts/bulk-delete: DELETE', // @todo: add tests '/discounts/bulk-update-status: PATCH', diff --git a/tests/UI/campaigns/functional/BO/03_catalog/01_products/14_detailsTab.ts b/tests/UI/campaigns/functional/BO/03_catalog/01_products/14_detailsTab.ts index ebe27ec07ee79..22806b0cf22be 100644 --- a/tests/UI/campaigns/functional/BO/03_catalog/01_products/14_detailsTab.ts +++ b/tests/UI/campaigns/functional/BO/03_catalog/01_products/14_detailsTab.ts @@ -432,12 +432,11 @@ describe('BO - Catalog - Products : Details tab', async () => { expect(pageTitle).to.contains(newProductData.name); }); - // @todo : https://github.com/PrestaShop/hummingbird/pull/898 - it.skip('should check the product condition', async function () { + it('should check the product condition', async function () { await testContext.addContextItem(this, 'testIdentifier', 'checkProductCondition', baseContext); const productCondition = await foHummingbirdProductPage.getProductCondition(page); - expect(productCondition).to.eq(`Condition ${editProductData.condition}`); + expect(productCondition).to.eq(editProductData.condition); }); it('should go back to BO', async function () { diff --git a/tests/UI/campaigns/functional/BO/03_catalog/01_products/17_pricingTab.ts b/tests/UI/campaigns/functional/BO/03_catalog/01_products/17_pricingTab.ts index 946e09dae8606..4667986e028f1 100644 --- a/tests/UI/campaigns/functional/BO/03_catalog/01_products/17_pricingTab.ts +++ b/tests/UI/campaigns/functional/BO/03_catalog/01_products/17_pricingTab.ts @@ -304,8 +304,7 @@ describe('BO - Catalog - Products : Pricing tab', async () => { expect(pageTitle).to.contains(newProductData.name); }); - // @todo : https://github.com/PrestaShop/hummingbird/issues/879 - it.skip('should check the on sale flag', async function () { + it('should check the on sale flag', async function () { await testContext.addContextItem(this, 'testIdentifier', 'checkOnSaleFlag', baseContext); const flagText = await foHummingbirdProductPage.getProductTag(page); diff --git a/tests/UI/campaigns/functional/BO/03_catalog/01_products/22_bulkActionsEnableDisable3DotsButton.ts b/tests/UI/campaigns/functional/BO/03_catalog/01_products/22_bulkActionsEnableDisable3DotsButton.ts index 6b27e38181751..85128a313ec76 100644 --- a/tests/UI/campaigns/functional/BO/03_catalog/01_products/22_bulkActionsEnableDisable3DotsButton.ts +++ b/tests/UI/campaigns/functional/BO/03_catalog/01_products/22_bulkActionsEnableDisable3DotsButton.ts @@ -20,7 +20,6 @@ describe('BO - Catalog - Products list : Bulk actions, Enable/Disable, 3-dot but let numberOfProducts: number = 0; let productName: string = ''; - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); diff --git a/tests/UI/campaigns/functional/BO/03_catalog/02_categories/02_CRUDCategoryInBO.ts b/tests/UI/campaigns/functional/BO/03_catalog/02_categories/02_CRUDCategoryInBO.ts index 17e04c46b073e..eaa24fd3d2b17 100644 --- a/tests/UI/campaigns/functional/BO/03_catalog/02_categories/02_CRUDCategoryInBO.ts +++ b/tests/UI/campaigns/functional/BO/03_catalog/02_categories/02_CRUDCategoryInBO.ts @@ -173,7 +173,7 @@ describe('BO - Catalog - Categories : CRUD Category in BO', async () => { // Check category name const pageTitle = await foHummingbirdCategoryPage.getHeaderPageName(page); - expect(pageTitle).to.contains(createCategoryData.name.toUpperCase()); + expect(pageTitle).to.contains(createCategoryData.name); // Check category description const categoryDescription = await foHummingbirdCategoryPage.getCategoryDescription(page); @@ -258,7 +258,7 @@ describe('BO - Catalog - Categories : CRUD Category in BO', async () => { // Check subcategory name const pageTitle = await foHummingbirdCategoryPage.getHeaderPageName(page); - expect(pageTitle).to.contains(createSubCategoryData.name.toUpperCase()); + expect(pageTitle).to.contains(createSubCategoryData.name); // Check subcategory description const subcategoryDescription = await foHummingbirdCategoryPage.getCategoryDescription(page); @@ -431,7 +431,7 @@ describe('BO - Catalog - Categories : CRUD Category in BO', async () => { // Check if it is redirected to the category const categoryName = await foHummingbirdCategoryPage.getHeaderPageName(page); - expect(categoryName).to.contains(arg.category.redirectedCategory!.name.toUpperCase()); + expect(categoryName).to.contains(arg.category.redirectedCategory!.name); }); it('should go back to BO', async function () { diff --git a/tests/UI/campaigns/functional/BO/03_catalog/02_categories/08_editHomeCategory.ts b/tests/UI/campaigns/functional/BO/03_catalog/02_categories/08_editHomeCategory.ts index 3d1af7b91e0d8..1a4e3aead6cfe 100644 --- a/tests/UI/campaigns/functional/BO/03_catalog/02_categories/08_editHomeCategory.ts +++ b/tests/UI/campaigns/functional/BO/03_catalog/02_categories/08_editHomeCategory.ts @@ -109,7 +109,7 @@ describe('BO - Catalog - Categories : Edit home category', async () => { // Check category name const pageTitle = await foHummingbirdCategoryPage.getHeaderPageName(page); - expect(pageTitle).to.contains(editCategoryData.name.toUpperCase()); + expect(pageTitle).to.contains(editCategoryData.name); // Check category description const categoryDescription = await foHummingbirdCategoryPage.getCategoryDescription(page); diff --git a/tests/UI/campaigns/functional/BO/08_design/05_positions/02_filterModule.ts b/tests/UI/campaigns/functional/BO/08_design/05_positions/02_filterModule.ts index 565df8a86278f..80e4b00aabb87 100644 --- a/tests/UI/campaigns/functional/BO/08_design/05_positions/02_filterModule.ts +++ b/tests/UI/campaigns/functional/BO/08_design/05_positions/02_filterModule.ts @@ -20,6 +20,8 @@ describe('BO - Design - Positions : Filter module', async () => { const hooks: string[] = [ 'displayAdminCustomers', + 'displayCustomerAccount', + 'displayFooter', 'displayMyAccountBlock', 'displayProductActions', ]; diff --git a/tests/UI/campaigns/functional/BO/08_design/06_imageSettings/14_checkCategoryImageFormat.ts b/tests/UI/campaigns/functional/BO/08_design/06_imageSettings/14_checkCategoryImageFormat.ts index def0c665a0a72..3f0571a00bcf5 100644 --- a/tests/UI/campaigns/functional/BO/08_design/06_imageSettings/14_checkCategoryImageFormat.ts +++ b/tests/UI/campaigns/functional/BO/08_design/06_imageSettings/14_checkCategoryImageFormat.ts @@ -282,8 +282,7 @@ describe('BO - Design - Image Settings : Check category image format', async () expect(isCategoryPageVisible, 'Home category page was not opened').to.eq(true); }); - // @todo : https://github.com/PrestaShop/hummingbird/issues/874 - it.skip('should check that the main image of the quick view is a WebP', async function () { + it('should check that the main image of the quick view is a WebP', async function () { await testContext.addContextItem(this, 'testIdentifier', `checkMainImageQuickView${argExtension}`, baseContext); const categoryImage = await foHummingbirdCategoryPage.getCategoryImageMain(page, arg.category.name); diff --git a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/02_productPage/04_separatorOfAttributeAnchor.ts b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/02_productPage/04_separatorOfAttributeAnchor.ts index 91473749e9c7a..723694c43b44f 100644 --- a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/02_productPage/04_separatorOfAttributeAnchor.ts +++ b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/02_productPage/04_separatorOfAttributeAnchor.ts @@ -24,7 +24,6 @@ describe('BO - Shop Parameters - Product Settings : Update separator of attribut const productAttributes: string[] = ['1', 'size', 's/8', 'color', 'white']; - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); @@ -57,18 +56,16 @@ describe('BO - Shop Parameters - Product Settings : Update separator of attribut expect(pageTitle).to.contains(boProductSettingsPage.pageTitle); }); - const tests = [ - {args: {option: ',', attributesInProductLink: productAttributes.join(',')}}, - {args: {option: '-', attributesInProductLink: productAttributes.join('-')}}, - ]; - - tests.forEach((test, index: number) => { - it(`should choose the separator option '${test.args.option}'`, async function () { + [ + {option: ',', attributesInProductLink: productAttributes.join(',')}, + {option: '-', attributesInProductLink: productAttributes.join('-')}, + ].forEach((arg, index: number) => { + it(`should choose the separator option '${arg.option}'`, async function () { await testContext.addContextItem(this, 'testIdentifier', `chooseOption_${index}`, baseContext); const result = await boProductSettingsPage.setSeparatorOfAttributeOnProductLink( page, - test.args.option, + arg.option, ); expect(result).to.contains(boProductSettingsPage.successfulUpdateMessage); }); @@ -97,7 +94,7 @@ describe('BO - Shop Parameters - Product Settings : Update separator of attribut await testContext.addContextItem(this, 'testIdentifier', `checkAttributeSeparator_${index}`, baseContext); const currentURL = await foHummingbirdProductPage.getProductPageURL(page); - expect(currentURL).to.contains(test.args.attributesInProductLink); + expect(currentURL).to.contains(arg.attributesInProductLink); }); it('should close the page and go back to BO', async function () { diff --git a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/06_labelOfInStockProducts.ts b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/06_labelOfInStockProducts.ts index 1184d2a11bd23..55917e2f243cf 100644 --- a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/06_labelOfInStockProducts.ts +++ b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/06_labelOfInStockProducts.ts @@ -20,7 +20,6 @@ describe('BO - Shop Parameters - Product Settings : Update label of in-stock pro let browserContext: BrowserContext; let page: Page; - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); @@ -87,11 +86,13 @@ describe('BO - Shop Parameters - Product Settings : Update label of in-stock pro it('should check the label of in-stock product in FO product page', async function () { await testContext.addContextItem(this, 'testIdentifier', `checkLabelInStock_${index}`, baseContext); - const isVisible = await foHummingbirdProductPage.isAvailabilityQuantityDisplayed(page); + const isVisible = await foHummingbirdProductPage.hasProductAvailabilityLabel(page); expect(isVisible).to.be.equal(test.args.exist); - const availabilityLabel = await foHummingbirdProductPage.getProductAvailabilityLabel(page); - expect(availabilityLabel).to.contains(test.args.labelToCheck); + if (test.args.exist) { + const availabilityLabel = await foHummingbirdProductPage.getProductAvailabilityLabel(page); + expect(availabilityLabel).to.contains(test.args.labelToCheck); + } }); it('should go back to BO', async function () { diff --git a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/07_labelOutOfStock.ts b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/07_labelOutOfStock.ts index b1d818611e69d..6ee9878e4b117 100644 --- a/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/07_labelOutOfStock.ts +++ b/tests/UI/campaigns/functional/BO/13_shopParameters/03_productSettings/03_productsStock/07_labelOutOfStock.ts @@ -18,8 +18,7 @@ import { const baseContext: string = 'functional_BO_shopParameters_productSettings_productsStock_labelOutOfStock'; -describe('BO - Shop Parameters - product Settings : Set label out-of-stock with ' - + 'allowed/denied backorders', async () => { +describe('BO - Shop Parameters - product Settings : Set label out-of-stock with allowed/denied backorders', async () => { let browserContext: BrowserContext; let page: Page; @@ -30,7 +29,6 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with labelWhenInStock: ' ', }); - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); @@ -101,49 +99,45 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with const tests = [ { - args: { - action: 'enable', - enable: true, - backordersAction: 'allowed', - label: 'You can order', - labelToCheck: 'You can order', - }, + action: 'enable', + enable: true, + backordersAction: 'allowed', + label: 'You can order', }, { - args: { - action: 'enable', enable: true, backordersAction: 'allowed', label: ' ', labelToCheck: '', - }, + action: 'enable', + enable: true, + backordersAction: 'allowed', + label: ' ', }, { - args: { - action: 'disable', enable: false, backordersAction: 'denied', label: ' ', labelToCheck: '', - }, + action: 'disable', + enable: false, + backordersAction: 'denied', + label: ' ', }, { - args: { - action: 'disable', - enable: false, - backordersAction: 'denied', - label: 'Out-of-Stock', - labelToCheck: 'Out-of-Stock', - }, + action: 'disable', + enable: false, + backordersAction: 'denied', + label: 'Out-of-Stock', }, ]; - tests.forEach((test, index: number) => { - it(`should ${test.args.action} allow ordering of out-of-stock products`, async function () { + tests.forEach((arg, index: number) => { + it(`should ${arg.action} allow ordering of out-of-stock products`, async function () { await testContext.addContextItem( this, 'testIdentifier', - `${test.args.action}AllowOrderingOutOfStock${index}`, + `${arg.action}AllowOrderingOutOfStock${index}`, baseContext, ); - const result = await boProductSettingsPage.setAllowOrderingOutOfStockStatus(page, test.args.enable); + const result = await boProductSettingsPage.setAllowOrderingOutOfStockStatus(page, arg.enable); expect(result).to.contains(boProductSettingsPage.successfulUpdateMessage); }); - it(`should set Label of out-of-stock products with ${test.args.backordersAction} backorders`, async function () { + it(`should set Label of out-of-stock products with ${arg.backordersAction} backorders`, async function () { await testContext.addContextItem( this, 'testIdentifier', @@ -153,10 +147,10 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with let result; - if (test.args.enable) { - result = await boProductSettingsPage.setLabelOosAllowedBackorders(page, test.args.label); + if (arg.enable) { + result = await boProductSettingsPage.setLabelOosAllowedBackorders(page, arg.label); } else { - result = await boProductSettingsPage.setLabelOosDeniedBackorders(page, test.args.label); + result = await boProductSettingsPage.setLabelOosDeniedBackorders(page, arg.label); } expect(result).to.contains(boProductSettingsPage.successfulUpdateMessage); @@ -166,7 +160,7 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with await testContext.addContextItem( this, 'testIdentifier', - `viewMyShop${test.args.action}${index}`, + `viewMyShop${arg.action}${index}`, baseContext, ); @@ -180,7 +174,7 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with await testContext.addContextItem( this, 'testIdentifier', - `goToProductPage${test.args.action}${index}`, + `goToProductPage${arg.action}${index}`, baseContext, ); @@ -196,16 +190,23 @@ describe('BO - Shop Parameters - product Settings : Set label out-of-stock with await testContext.addContextItem( this, 'testIdentifier', - `checkOrderingOutOfStock${test.args.action}${index}`, + `checkOrderingOutOfStock${arg.action}${index}`, baseContext, ); + const hasLabel: boolean = arg.label.trim() !== ''; + // Check quantity and availability label const lastQuantityIsVisible = await foHummingbirdProductPage.isAddToCartButtonEnabled(page); - expect(lastQuantityIsVisible).to.be.equal(test.args.enable); + expect(lastQuantityIsVisible).to.be.equal(arg.enable); + + const hasProductAvailabilityLabel = await foHummingbirdProductPage.hasProductAvailabilityLabel(page); + expect(hasProductAvailabilityLabel).to.equals(hasLabel); - const availabilityLabel = await foHummingbirdProductPage.getProductAvailabilityLabel(page); - expect(availabilityLabel).to.contains(test.args.labelToCheck); + if (hasLabel) { + const availabilityLabel = await foHummingbirdProductPage.getProductAvailabilityLabel(page); + expect(availabilityLabel).to.contains(arg.label); + } }); it('should go back to BO', async function () { diff --git a/tests/UI/campaigns/functional/FO/classic/03_userAccount/05_getGDPRDataInCSV.ts b/tests/UI/campaigns/functional/FO/classic/03_userAccount/05_getGDPRDataInCSV.ts index 108d681b32f6c..6447c6ec69a91 100644 --- a/tests/UI/campaigns/functional/FO/classic/03_userAccount/05_getGDPRDataInCSV.ts +++ b/tests/UI/campaigns/functional/FO/classic/03_userAccount/05_getGDPRDataInCSV.ts @@ -252,7 +252,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { true, 'utf16le', ); - expect(isVisible, 'General info is not correct!').to.eq(true); + expect(isVisible).to.eq(true); }); it('should check that Addresses table is empty', async function () { @@ -265,7 +265,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { true, 'utf16le', ); - expect(isVisible, 'Addresses table is not empty!').to.eq(true); + expect(isVisible).to.eq(true); }); it('should check that Orders table is empty', async function () { @@ -278,7 +278,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { true, 'utf16le', ); - expect(isVisible, 'Orders table is not empty!').to.eq(true); + expect(isVisible).to.eq(true); }); it('should check that Carts table is empty', async function () { @@ -291,7 +291,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { true, 'utf16le', ); - expect(isVisible, 'Carts table is not empty!').to.eq(true); + expect(isVisible).to.eq(true); }); it('should check that Messages table is empty', async function () { @@ -326,7 +326,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - '"MODULE:NEWSLETTERSUBSCRIPTION""Newslettersubscription:noemailtoexport,thiscustomerhasnotregistered.""', + '"MODULE:NEWSLETTERSUBSCRIPTION""Newslettersubscription:noemailtoexport,thiscustomerhasnotregistered."', true, true, 'utf16le', @@ -339,7 +339,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - '""MODULE:PRODUCTCOMMENTS""MODULE:MAILALERTS"', + '""MODULE:PRODUCTCOMMENTS""MODULE:NEWSLETTERSUBSCRIPTION"', true, true, 'utf16le', @@ -352,7 +352,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - 'MODULE:MAILALERTS""Mailalert:Unabletoexportcustomerusingemail."', + '"MODULE:MAILALERTS""Mailalert:Unabletoexportcustomerusingemail."', true, true, 'utf16le', diff --git a/tests/UI/campaigns/functional/FO/hummingbird/03_userAccount/05_getGDPRDataInCSV.ts b/tests/UI/campaigns/functional/FO/hummingbird/03_userAccount/05_getGDPRDataInCSV.ts index 4d3c26aadfad3..fc56ee9ebb28a 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/03_userAccount/05_getGDPRDataInCSV.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/03_userAccount/05_getGDPRDataInCSV.ts @@ -87,7 +87,6 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const createCustomerName: string = `${customerData.firstName[0]}. ${customerData.lastName}`; - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); @@ -319,7 +318,7 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - '"MODULE:NEWSLETTERSUBSCRIPTION""Newslettersubscription:noemailtoexport,thiscustomerhasnotregistered.""', + '"MODULE:NEWSLETTERSUBSCRIPTION""Newslettersubscription:noemailtoexport,thiscustomerhasnotregistered."', true, true, 'utf16le', @@ -332,12 +331,12 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - '""MODULE:PRODUCTCOMMENTS""MODULE:MAILALERTS"', + '""MODULE:PRODUCTCOMMENTS""MODULE:NEWSLETTERSUBSCRIPTION"', true, true, 'utf16le', ); - expect(isVisible, 'Products comments is not empty!').to.eq(true); + expect(isVisible).to.eq(true); }); it('should check that mail alerts table is empty', async function () { @@ -345,12 +344,12 @@ describe('FO - Account : Get GDPR data in CSV', async () => { const isVisible = await utilsFile.isTextInFile( filePath, - 'MODULE:MAILALERTS""Mailalert:Unabletoexportcustomerusingemail."', + '"MODULE:MAILALERTS""Mailalert:Unabletoexportcustomerusingemail."', true, true, 'utf16le', ); - expect(isVisible, 'Mail alert table is not empty!').to.eq(true); + expect(isVisible).to.eq(true); }); }); }); diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/01_quickView/06_changeCombination.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/01_quickView/06_changeCombination.ts index 82d4dfcca7e89..dcafebe02fd9c 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/01_quickView/06_changeCombination.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/01_quickView/06_changeCombination.ts @@ -104,7 +104,7 @@ describe('FO - Product page - Quick view : Change combination', async () => { await foHummingbirdModalQuickViewPage.setAttribute(page, secondAttributes[1]); const quickViewImageMain = await foHummingbirdModalQuickViewPage.getQuickViewImageMain(page); - expect(quickViewImageMain).to.contains('1-home_default'); + expect(quickViewImageMain).to.contains('1-default_xl'); }); it('should select the color white and check the cover image', async function () { @@ -113,7 +113,7 @@ describe('FO - Product page - Quick view : Change combination', async () => { await foHummingbirdModalQuickViewPage.setAttribute(page, firstAttributes[1]); const quickViewImageMain = await foHummingbirdModalQuickViewPage.getQuickViewImageMain(page); - expect(quickViewImageMain).to.contains('2-home_default'); + expect(quickViewImageMain).to.contains('2-default_xl'); }); it('should close the quick view modal', async function () { diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts index fc14c5ee7fcdd..2add99348973c 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts @@ -57,13 +57,13 @@ describe('FO - Product page : Change quantity', async () => { it('should change the quantity by using the arrow \'Down\' button', async function () { await testContext.addContextItem(this, 'testIdentifier', 'decrement', baseContext); - await foHummingbirdProductPage.setQuantityByArrowUpDown(page, 1, 'down'); + await foHummingbirdProductPage.setQuantityByArrowUpDown(page, 1, 'decrement'); const productQuantity = await foHummingbirdProductPage.getProductQuantity(page); expect(productQuantity).to.equal(1); }); - it('should change the quantity by using the arrow \'UP\' button', async function () { + it('should change the quantity by using the arrow \'Up\' button', async function () { await testContext.addContextItem(this, 'testIdentifier', 'incrementQuantity', baseContext); await foHummingbirdProductPage.setQuantityByArrowUpDown(page, 2, 'increment'); diff --git a/tests/UI/campaigns/modules/02_blockwishlist/01_installation/04_resetModule.ts b/tests/UI/campaigns/modules/02_blockwishlist/01_installation/04_resetModule.ts index 07a556aee7ec2..3deb31d8d493a 100644 --- a/tests/UI/campaigns/modules/02_blockwishlist/01_installation/04_resetModule.ts +++ b/tests/UI/campaigns/modules/02_blockwishlist/01_installation/04_resetModule.ts @@ -14,7 +14,7 @@ import { dataProducts, foHummingbirdHomePage, foHummingbirdLoginPage, - foClassicModalWishlistPage, + foHummingbirdModalWishlistPage, foHummingbirdMyWishlistsViewPage, foHummingbirdProductPage, foHummingbirdSearchResultsPage, @@ -161,14 +161,14 @@ describe('Wishlist module - Reset module', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.getModalAddToCreateWislistLabel(page); + const textResult = await foHummingbirdModalWishlistPage.getModalAddToCreateWislistLabel(page); expect(textResult).to.contains(labelButton); }); it('should go to \'Modules > Module Manager\' page', async function () { await testContext.addContextItem(this, 'testIdentifier', 'goToModuleManagerPageForReset', baseContext); - page = await foClassicModalWishlistPage.changePage(browserContext, 0); + page = await foHummingbirdModalWishlistPage.changePage(browserContext, 0); await boDashboardPage.goToSubMenu( page, boDashboardPage.modulesParentLink, @@ -201,7 +201,7 @@ describe('Wishlist module - Reset module', async () => { await foHummingbirdProductPage.reloadPage(page); await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.getModalAddToCreateWislistLabel(page); + const textResult = await foHummingbirdModalWishlistPage.getModalAddToCreateWislistLabel(page); expect(textResult).to.contains(modBlockwishlistBoMain.defaultValueCreateButtonLabel); }); }); diff --git a/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/01_lists/03_shareList.ts b/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/01_lists/03_shareList.ts index 15d8b0734be5b..acea9ecea4753 100644 --- a/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/01_lists/03_shareList.ts +++ b/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/01_lists/03_shareList.ts @@ -7,7 +7,7 @@ import { dataModules, foHummingbirdHomePage, foHummingbirdLoginPage, - foClassicModalWishlistPage, + foHummingbirdModalWishlistPage, foHummingbirdMyAccountPage, foHummingbirdMyWishlistsPage, foHummingbirdMyWishlistsViewPage, @@ -90,10 +90,10 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickShareWishlistButton(page, 1); - const hasModalShare = await foClassicModalWishlistPage.hasModalShare(page); + const hasModalShare = await foHummingbirdModalWishlistPage.hasModalShare(page); expect(hasModalShare).to.equal(true); - const isModalVisible = await foClassicModalWishlistPage.clickCancelOnModalShare(page); + const isModalVisible = await foHummingbirdModalWishlistPage.clickCancelOnModalShare(page); expect(isModalVisible).to.equal(false); }); @@ -102,11 +102,11 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickShareWishlistButton(page, 1); - const hasModalLogin = await foClassicModalWishlistPage.hasModalShare(page); + const hasModalLogin = await foHummingbirdModalWishlistPage.hasModalShare(page); expect(hasModalLogin).to.equal(true); - const textToast = await foClassicModalWishlistPage.clickShareOnModalShare(page); - expect(textToast).to.equal(foClassicModalWishlistPage.messageLinkSharedWishlist); + const textToast = await foHummingbirdModalWishlistPage.clickShareOnModalShare(page); + expect(textToast).to.equal(foHummingbirdModalWishlistPage.messageLinkSharedWishlist); }); it('should click on the Create new list link and cancel', async function () { @@ -114,10 +114,10 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickCreateWishlistButton(page); - const hasModalCreate = await foClassicModalWishlistPage.hasModalCreate(page); + const hasModalCreate = await foHummingbirdModalWishlistPage.hasModalCreate(page); expect(hasModalCreate).to.equal(true); - const isModalVisible = await foClassicModalWishlistPage.clickCancelOnModalCreate(page); + const isModalVisible = await foHummingbirdModalWishlistPage.clickCancelOnModalCreate(page); expect(isModalVisible).to.equal(false); }); @@ -126,13 +126,13 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickCreateWishlistButton(page); - const hasModalCreate = await foClassicModalWishlistPage.hasModalCreate(page); + const hasModalCreate = await foHummingbirdModalWishlistPage.hasModalCreate(page); expect(hasModalCreate).to.equal(true); - await foClassicModalWishlistPage.setNameOnModalCreate(page, wishlistName); + await foHummingbirdModalWishlistPage.setNameOnModalCreate(page, wishlistName); - const textToast = await foClassicModalWishlistPage.clickCreateOnModalCreate(page); - expect(textToast).to.equal(foClassicModalWishlistPage.messageWishlistCreated); + const textToast = await foHummingbirdModalWishlistPage.clickCreateOnModalCreate(page); + expect(textToast).to.equal(foHummingbirdModalWishlistPage.messageWishlistCreated); }); it('should click on the share icon (in dropdown) and cancel the modal', async function () { @@ -140,10 +140,10 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickShareWishlistButton(page, 2); - const hasModalShare = await foClassicModalWishlistPage.hasModalShare(page); + const hasModalShare = await foHummingbirdModalWishlistPage.hasModalShare(page); expect(hasModalShare).to.equal(true); - const isModalVisible = await foClassicModalWishlistPage.clickCancelOnModalShare(page); + const isModalVisible = await foHummingbirdModalWishlistPage.clickCancelOnModalShare(page); expect(isModalVisible).to.equal(false); }); @@ -152,11 +152,11 @@ describe('Wishlist module - Share a list', async () => { await foHummingbirdMyWishlistsPage.clickShareWishlistButton(page, 2); - const hasModalLogin = await foClassicModalWishlistPage.hasModalShare(page); + const hasModalLogin = await foHummingbirdModalWishlistPage.hasModalShare(page); expect(hasModalLogin).to.equal(true); - const textToast = await foClassicModalWishlistPage.clickShareOnModalShare(page); - expect(textToast).to.equal(foClassicModalWishlistPage.messageLinkSharedWishlist); + const textToast = await foHummingbirdModalWishlistPage.clickShareOnModalShare(page); + expect(textToast).to.equal(foHummingbirdModalWishlistPage.messageLinkSharedWishlist); wishlistUrl = await foHummingbirdMyWishlistsPage.getClipboardText(page); expect(wishlistUrl).to.be.a('string'); diff --git a/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/02_products/01_addProductToList.ts b/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/02_products/01_addProductToList.ts index 108698fca8f27..edf813fd9633f 100644 --- a/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/02_products/01_addProductToList.ts +++ b/tests/UI/campaigns/modules/02_blockwishlist/03_frontOffice/02_products/01_addProductToList.ts @@ -12,7 +12,7 @@ import { FakerProduct, foHummingbirdHomePage, foHummingbirdLoginPage, - foClassicModalWishlistPage, + foHummingbirdModalWishlistPage, foHummingbirdMyAccountPage, foHummingbirdMyWishlistsPage, foHummingbirdMyWishlistsViewPage, @@ -90,10 +90,10 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const hasModalLogin = await foClassicModalWishlistPage.hasModalLogin(page); + const hasModalLogin = await foHummingbirdModalWishlistPage.hasModalLogin(page); expect(hasModalLogin).to.equal(true); - const isModalVisible = await foClassicModalWishlistPage.clickCancelOnModalLogin(page); + const isModalVisible = await foHummingbirdModalWishlistPage.clickCancelOnModalLogin(page); expect(isModalVisible).to.equal(false); }); @@ -102,10 +102,10 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const hasModalLogin = await foClassicModalWishlistPage.hasModalLogin(page); + const hasModalLogin = await foHummingbirdModalWishlistPage.hasModalLogin(page); expect(hasModalLogin).to.equal(true); - await foClassicModalWishlistPage.clickLoginOnModalLogin(page); + await foHummingbirdModalWishlistPage.clickLoginOnModalLogin(page); const pageTitle = await foHummingbirdLoginPage.getPageTitle(page); expect(pageTitle).to.contains(foHummingbirdLoginPage.pageTitle); @@ -165,7 +165,7 @@ describe('Wishlist module - Add a product to a list', async () => { const pageTitle = await foHummingbirdProductPage.getPageTitle(page); expect(pageTitle).to.equal(dataProducts.demo_3.name); - await foHummingbirdProductPage.setQuantityByArrowUpDown(page, 5, 'up'); + await foHummingbirdProductPage.setQuantityByArrowUpDown(page, 5, 'increment'); }); it('should add to the wishlist and select the first wishlist', async function () { @@ -173,8 +173,8 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.addWishlist(page, 1); - expect(textResult).to.equal(foClassicModalWishlistPage.messageAddedToWishlist); + const textResult = await foHummingbirdModalWishlistPage.addWishlist(page, 1); + expect(textResult).to.equal(foHummingbirdModalWishlistPage.messageAddedToWishlist); }); it('should go to "My Account" page', async function () { @@ -213,8 +213,9 @@ describe('Wishlist module - Add a product to a list', async () => { const nameProduct = await foHummingbirdMyWishlistsViewPage.getProductName(page, 1); expect(nameProduct).to.equal(dataProducts.demo_3.name); - const qtyProduct = await foHummingbirdMyWishlistsViewPage.getProductQuantity(page, 1); - expect(qtyProduct).to.equal(5); + // @todo : https://github.com/PrestaShop/hummingbird/issues/908 + //const qtyProduct = await foHummingbirdMyWishlistsViewPage.getProductQuantity(page, 1); + //expect(qtyProduct).to.equal(5); const sizeProduct = await foHummingbirdMyWishlistsViewPage.getProductAttribute(page, 1, 'Size'); expect(sizeProduct).to.equal('S'); @@ -235,8 +236,8 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.addWishlist(page, 1); - expect(textResult).to.equal(foClassicModalWishlistPage.messageAddedToWishlist); + const textResult = await foHummingbirdModalWishlistPage.addWishlist(page, 1); + expect(textResult).to.equal(foHummingbirdModalWishlistPage.messageAddedToWishlist); }); it('should go to "My Account" page', async function () { @@ -300,8 +301,8 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.addWishlist(page, 1); - expect(textResult).to.equal(foClassicModalWishlistPage.messageAddedToWishlist); + const textResult = await foHummingbirdModalWishlistPage.addWishlist(page, 1); + expect(textResult).to.equal(foHummingbirdModalWishlistPage.messageAddedToWishlist); }); it('should go to "My Account" page', async function () { @@ -357,17 +358,22 @@ describe('Wishlist module - Add a product to a list', async () => { expect(pageTitle).to.equal(dataProducts.demo_1.name); }); - it('should select the size \'M\' / color "Black" and check it', async function () { - await testContext.addContextItem(this, 'testIdentifier', 'selectSizeColor', baseContext); + it('should select the size \'M\' and check it', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'selectSize', baseContext); await foHummingbirdProductPage.selectAttributes(page, 'select', [{name: 'size', value: 'M'}]); - await foHummingbirdProductPage.selectAttributes(page, 'radio', [{name: 'Color', value: 'Black'}], 2); const selectedAttributeSize = await foHummingbirdProductPage.getSelectedAttribute(page, 1, 'select'); expect(selectedAttributeSize).to.equal('M'); + }); + + it('should select the color "Black" and check it', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'selectColor', baseContext); + + await foHummingbirdProductPage.selectAttributes(page, 'radio', [{name: 'Color', value: 'Black'}], 2); const selectedAttributeColor = await foHummingbirdProductPage.getSelectedAttribute(page, 2, 'radio'); - expect(selectedAttributeColor).to.equal('Black'); + expect(selectedAttributeColor).to.equal('Color - Black'); }); it('should add to the wishlist and select the first wishlist', async function () { @@ -375,8 +381,8 @@ describe('Wishlist module - Add a product to a list', async () => { await foHummingbirdProductPage.clickAddToWishlistButton(page); - const textResult = await foClassicModalWishlistPage.addWishlist(page, 1); - expect(textResult).to.equal(foClassicModalWishlistPage.messageAddedToWishlist); + const textResult = await foHummingbirdModalWishlistPage.addWishlist(page, 1); + expect(textResult).to.equal(foHummingbirdModalWishlistPage.messageAddedToWishlist); }); it('should go to "My Account" page', async function () { diff --git a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/01_uninstallAndInstallModule.ts b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/01_uninstallAndInstallModule.ts index 21b877b34e5a1..f2b1cf48d810d 100644 --- a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/01_uninstallAndInstallModule.ts +++ b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/01_uninstallAndInstallModule.ts @@ -174,9 +174,8 @@ describe('Mail alerts module - Uninstall and install module', async () => { const pageTitle = await foHummingbirdProductPage.getPageTitle(page); expect(pageTitle.toUpperCase()).to.contains(productOutOfStockNotAllowed.name.toUpperCase()); - // @todo : https://github.com/PrestaShop/hummingbird/issues/879 - // const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); - // expect(hasFlagOutOfStock).to.be.equal(true); + const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); + expect(hasFlagOutOfStock).to.be.equal(true); const hasBlockMailAlert = await foHummingbirdProductPage.hasBlockMailAlert(page); expect(hasBlockMailAlert).to.be.equal(false); @@ -235,9 +234,8 @@ describe('Mail alerts module - Uninstall and install module', async () => { const pageTitle = await foHummingbirdProductPage.getPageTitle(page); expect(pageTitle.toUpperCase()).to.contains(productOutOfStockNotAllowed.name.toUpperCase()); - // @todo : https://github.com/PrestaShop/hummingbird/issues/879 - // const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); - // expect(hasFlagOutOfStock).to.be.equal(true); + const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); + expect(hasFlagOutOfStock).to.be.equal(true); const hasBlockMailAlert = await foHummingbirdProductPage.hasBlockMailAlert(page); expect(hasBlockMailAlert).to.be.equal(true); diff --git a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/03_uninstallAndDeleteModule.ts b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/03_uninstallAndDeleteModule.ts index ba6880916e4c5..b18dd28ee789d 100644 --- a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/03_uninstallAndDeleteModule.ts +++ b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/03_uninstallAndDeleteModule.ts @@ -179,9 +179,8 @@ describe('Mail alerts module - Uninstall and delete module', async () => { const pageTitle = await foHummingbirdProductPage.getPageTitle(page); expect(pageTitle.toUpperCase()).to.contains(productOutOfStockNotAllowed.name.toUpperCase()); - // @todo : https://github.com/PrestaShop/hummingbird/issues/879 - // const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); - // expect(hasFlagOutOfStock).to.be.equal(true); + const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); + expect(hasFlagOutOfStock).to.be.equal(true); const hasBlockMailAlert = await foHummingbirdProductPage.hasBlockMailAlert(page); expect(hasBlockMailAlert).to.be.equal(false); diff --git a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/05_disableEnableModule.ts b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/05_disableEnableModule.ts index c67f9846e03c8..270e5de844aaa 100644 --- a/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/05_disableEnableModule.ts +++ b/tests/UI/campaigns/modules/20_ps_emailalerts/01_installation/05_disableEnableModule.ts @@ -166,9 +166,8 @@ describe('Mail alerts module - Disable/Enable module', async () => { const pageTitle = await foHummingbirdProductPage.getPageTitle(page); expect(pageTitle.toUpperCase()).to.contains(productOutOfStockNotAllowed.name.toUpperCase()); - // @todo : https://github.com/PrestaShop/hummingbird/issues/879 - // const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); - // expect(hasFlagOutOfStock).to.be.equal(true); + const hasFlagOutOfStock = await foHummingbirdProductPage.hasProductFlag(page, 'out_of_stock'); + expect(hasFlagOutOfStock).to.be.equal(true); const hasBlockMailAlert = await foHummingbirdProductPage.hasBlockMailAlert(page); expect(hasBlockMailAlert).to.be.equal(test.state); diff --git a/tests/UI/campaigns/modules/20_ps_emailalerts/02_configuration/01_customerNotifications/01_enableDisableProductAvailability.ts b/tests/UI/campaigns/modules/20_ps_emailalerts/02_configuration/01_customerNotifications/01_enableDisableProductAvailability.ts index 37d278d1ed384..f78e84227f1a4 100644 --- a/tests/UI/campaigns/modules/20_ps_emailalerts/02_configuration/01_customerNotifications/01_enableDisableProductAvailability.ts +++ b/tests/UI/campaigns/modules/20_ps_emailalerts/02_configuration/01_customerNotifications/01_enableDisableProductAvailability.ts @@ -321,8 +321,9 @@ describe('Mail alerts module - Customer notifications - Enable/Disable product a await page.reload(); - const textMessage = await foHummingbirdProductPage.getBlockMailAlertNotification(page); - expect(textMessage).to.be.equal(foHummingbirdProductPage.messageAlertNotificationAlreadyRegistered); + // @todo : https://github.com/PrestaShop/hummingbird/issues/910 + //const textMessage = await foHummingbirdProductPage.getBlockMailAlertNotification(page); + //expect(textMessage).to.be.equal(foHummingbirdProductPage.messageAlertNotificationAlreadyRegistered); }); }); diff --git a/tests/UI/campaigns/modules/22_ps_facetedsearch/01_installation/05_resetModule.ts b/tests/UI/campaigns/modules/22_ps_facetedsearch/01_installation/05_resetModule.ts index e7d712ea6fd05..e263e6fc72c33 100644 --- a/tests/UI/campaigns/modules/22_ps_facetedsearch/01_installation/05_resetModule.ts +++ b/tests/UI/campaigns/modules/22_ps_facetedsearch/01_installation/05_resetModule.ts @@ -114,7 +114,7 @@ describe('Faceted search module - Reset module', async () => { it('should check the "All products" page', async function () { await testContext.addContextItem(this, 'testIdentifier', 'goToAllProductsPage', baseContext); - await foHummingbirdHomePage.goToAllProductsBlockPage(page, 1); + await foHummingbirdHomePage.goToAllProductsPage(page); const isCategoryPageVisible = await foHummingbirdCategoryPage.isCategoryPage(page); expect(isCategoryPageVisible).to.be.eq(true); @@ -203,7 +203,7 @@ describe('Faceted search module - Reset module', async () => { it('should check the "All products" page', async function () { await testContext.addContextItem(this, 'testIdentifier', 'goToAllProductsPage1', baseContext); - await foHummingbirdHomePage.goToAllProductsBlockPage(page, 1); + await foHummingbirdHomePage.goToAllProductsPage(page); const isCategoryPageVisible = await foHummingbirdCategoryPage.isCategoryPage(page); expect(isCategoryPageVisible).to.be.eq(true); diff --git a/tests/UI/campaigns/modules/37_psgdpr/02_configuration/03_consentCheckboxCustomization.ts b/tests/UI/campaigns/modules/37_psgdpr/02_configuration/03_consentCheckboxCustomization.ts index f283adb335809..ff5bed55e7244 100644 --- a/tests/UI/campaigns/modules/37_psgdpr/02_configuration/03_consentCheckboxCustomization.ts +++ b/tests/UI/campaigns/modules/37_psgdpr/02_configuration/03_consentCheckboxCustomization.ts @@ -1,6 +1,6 @@ import testContext from '@utils/testContext'; import {expect} from 'chai'; -import {faker, fakerFR} from '@faker-js/faker'; +import {faker} from '@faker-js/faker'; // Import commonTests import {createProductTest, deleteProductTest} from '@commonTests/BO/catalog/product'; @@ -37,13 +37,14 @@ const baseContext: string = 'modules_psgdpr_configuration_consentCheckboxCustomi describe('GDPR : Consent checkbox customization', async () => { let browserContext: BrowserContext; let page: Page; - const messageAccountCreation: string = faker.lorem.sentence(); - const messageCustomerAccount: string = faker.lorem.sentence(); - const messageNewsletter: string = faker.lorem.sentence(); - const messageContactForm: string = faker.lorem.sentence(); - const messageProductComments: string = faker.lorem.sentence(); - const messageMailAlerts: string = faker.lorem.sentence(); - const messageMailAlertsFR: string = fakerFR.lorem.sentence(); + const messageBase: string = faker.lorem.sentence(); + const messageAccountCreation: string = `Account Creation - ${messageBase}`; + const messageCustomerAccount: string = `Customer Account - ${messageBase}`; + const messageNewsletter: string = `Newsletter - ${messageBase}`; + const messageContactForm: string = `Contact Form - ${messageBase}`; + const messageProductComments: string = `Product Comments - ${messageBase}`; + const messageMailAlerts: string = `Mail Alerts EN - ${messageBase}`; + const messageMailAlertsFR: string = `Mail Alerts FR - ${messageBase}`; const customerData: FakerCustomer = new FakerCustomer(); const productOutOfStock: FakerProduct = new FakerProduct({ quantity: 0, @@ -52,7 +53,6 @@ describe('GDPR : Consent checkbox customization', async () => { createProductTest(productOutOfStock, `${baseContext}_preTest_0`); describe('Consent checkbox customization', async () => { - // before and after functions before(async function () { browserContext = await utilsPlaywright.createBrowserContext(this.browser); page = await utilsPlaywright.newTab(browserContext); @@ -452,6 +452,11 @@ describe('GDPR : Consent checkbox customization', async () => { const successMessage = await modPsGdprBoTabDataConsent.saveForm(page); expect(successMessage).to.be.contains(modPsGdprBoTabDataConsent.saveFormMessage); + + await page.screenshot({ + path: `${global.SCREENSHOT.FOLDER}/gdpr_00.png`, + fullPage: true, + }); }); it('should check on Contact Form the GDPR Label', async function () { diff --git a/tests/UI/package-lock.json b/tests/UI/package-lock.json index 5fb0ef2ef3269..28c19221b6d29 100644 --- a/tests/UI/package-lock.json +++ b/tests/UI/package-lock.json @@ -534,7 +534,7 @@ }, "node_modules/@prestashop-core/ui-testing": { "version": "0.0.12", - "resolved": "git+ssh://git@github.com/PrestaShop/ui-testing-library.git#e0c93bbbdee39d0415b96ff4ea0c1cc9b6cbf2cc", + "resolved": "git+ssh://git@github.com/PrestaShop/ui-testing-library.git#8e86150dfb5ec99980384e33ccd0ad5217ce123b", "license": "MIT", "dependencies": { "@faker-js/faker": "^10.1.0", @@ -8704,7 +8704,7 @@ } }, "@prestashop-core/ui-testing": { - "version": "git+ssh://git@github.com/PrestaShop/ui-testing-library.git#e0c93bbbdee39d0415b96ff4ea0c1cc9b6cbf2cc", + "version": "git+ssh://git@github.com/PrestaShop/ui-testing-library.git#8e86150dfb5ec99980384e33ccd0ad5217ce123b", "from": "@prestashop-core/ui-testing@https://github.com/PrestaShop/ui-testing-library#main", "requires": { "@faker-js/faker": "^10.1.0", diff --git a/tools/profiling/Profiler.php b/tools/profiling/Profiler.php index 9e6ec900b0854..3f20a90d8088e 100644 --- a/tools/profiling/Profiler.php +++ b/tools/profiling/Profiler.php @@ -213,7 +213,9 @@ public function processData() { // Including a lot of files uses memory foreach (get_included_files() as $file) { - $this->totalFilesize += filesize($file); + if (file_exists($file)) { + $this->totalFilesize += filesize($file); + } } foreach ($GLOBALS as $key => $value) {