Skip to content

Commit

Permalink
Merge pull request #6340 from magento-tsg-csl3/2.4-develop-pr45
Browse files Browse the repository at this point in the history
[TSG-CSL3] For 2.4 (pr45)
  • Loading branch information
viktym committed Nov 10, 2020
2 parents c644b3d + 6fa94aa commit 0a55921
Show file tree
Hide file tree
Showing 17 changed files with 813 additions and 146 deletions.
8 changes: 8 additions & 0 deletions app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Magento\Customer\Model\Indexer\CustomerGroupDimensionProvider;
use Magento\Store\Model\Indexer\WebsiteDimensionProvider;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\CatalogInventory\Model\Stock;

/**
* Bundle products Price indexer resource model
Expand Down Expand Up @@ -624,6 +625,13 @@ private function calculateDynamicBundleSelectionPrice($dimensions)
'tier_price' => $tierExpr,
]
);
$select->join(
['si' => $this->getTable('cataloginventory_stock_status')],
'si.product_id = bs.product_id',
[]
);
$select->where('si.stock_status = ?', Stock::STOCK_IN_STOCK);

$this->tableMaintainer->insertFromSelect($select, $this->getBundleSelectionTable(), []);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="StorefrontBundlePlaceOrderWithVirtualAndSimpleChildrenTest">
<annotations>
<features value="Bundle"/>
<stories value="Bundle product placing order"/>
<title value="Admin should be able to invoice order for the bundle product with virtual and simple products in options"/>
<description value="Place order for bundle product and create invoice"/>
<severity value="MAJOR"/>
<testCaseId value="MC-38683"/>
<useCaseId value="MC-37663"/>
<group value="Bundle"/>
</annotations>
<before>
<createData entity="CustomerEntityOne" stepKey="createCustomer"/>
<!--Create bundle product with fixed price with simple and virtual products in options-->
<createData entity="SimpleProduct2" stepKey="createSimpleProduct">
<field key="price">100.00</field>
</createData>
<createData entity="VirtualProduct" stepKey="createVirtualProduct">
<field key="price">50.00</field>
</createData>
<createData entity="ApiFixedBundleProduct" stepKey="createFixedBundleProduct"/>
<createData entity="DropDownBundleOption" stepKey="createFirstBundleOption">
<requiredEntity createDataKey="createFixedBundleProduct"/>
</createData>
<createData entity="DropDownBundleOption" stepKey="createSecondBundleOption">
<requiredEntity createDataKey="createFixedBundleProduct"/>
</createData>
<createData entity="ApiBundleLink" stepKey="firstLinkOptionToFixedProduct">
<requiredEntity createDataKey="createFixedBundleProduct"/>
<requiredEntity createDataKey="createFirstBundleOption"/>
<requiredEntity createDataKey="createSimpleProduct"/>
</createData>
<createData entity="ApiBundleLink" stepKey="secondLinkOptionToFixedProduct">
<requiredEntity createDataKey="createFixedBundleProduct"/>
<requiredEntity createDataKey="createSecondBundleOption"/>
<requiredEntity createDataKey="createVirtualProduct"/>
</createData>
<actionGroup stepKey="loginToAdminPanel" ref="AdminLoginActionGroup"/>
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProductEditPage">
<argument name="productId" value="$createFixedBundleProduct.id$"/>
</actionGroup>
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
<!--Perform reindex and flush cache-->
<actionGroup ref="AdminReindexAndFlushCache" stepKey="reindexAndFlushCache"/>
</before>
<after>
<deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProductForBundleItem"/>
<deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProductForBundleItem"/>
<deleteData createDataKey="createFixedBundleProduct" stepKey="deleteBundleProduct"/>
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
<actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilters"/>
<waitForPageLoad stepKey="waitForClearProductsGridFilters"/>
</after>
<!--Login customer on storefront-->
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginCustomer">
<argument name="Customer" value="$$createCustomer$$" />
</actionGroup>
<!--Open Product Page-->
<actionGroup ref="StorefrontOpenProductEntityPageActionGroup" stepKey="openBundleProductPage">
<argument name="product" value="$createFixedBundleProduct$"/>
</actionGroup>
<!--Add bundle to cart-->
<actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickAddToCart">
<argument name="productUrl" value="$createFixedBundleProduct.name$"/>
</actionGroup>
<actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart">
<argument name="quantity" value="1"/>
</actionGroup>
<!--Navigate to checkout-->
<actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="openCheckoutPage"/>
<!--Click next button to open payment section-->
<actionGroup ref="StorefrontCheckoutClickNextButtonActionGroup" stepKey="clickNext"/>
<!--Click place order-->
<actionGroup ref="ClickPlaceOrderActionGroup" stepKey="placeOrder"/>
<grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/>
<!--Order review page has address that was created during checkout-->
<actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById">
<argument name="orderId" value="{$grabOrderNumber}"/>
</actionGroup>
<!--Create Invoice for this Order-->
<actionGroup ref="StartCreateInvoiceFromOrderPageActionGroup" stepKey="createInvoice"/>
<actionGroup ref="SubmitInvoiceActionGroup" stepKey="submitInvoice"/>
</test>
</tests>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<!--Update Product Name and Description attribute-->
<actionGroup name="AdminMassUpdateProductQtyAndStockStatusActionGroup">
<arguments>
<argument name="attributes"/>
<argument name="product"/>
</arguments>
<!--Filter product in product grid-->
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPageFirstTime"/>
<waitForPageLoad stepKey="waitForProductGridPageLoad"/>
<conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFiltersInitial"/>
<click selector="{{AdminProductGridFilterSection.filters}}" stepKey="openProductFilters"/>
<fillField selector="{{AdminProductGridFilterSection.nameFilter}}" userInput="{{product.name}}" stepKey="fillProductNameFilter"/>
<fillField selector="{{AdminProductGridFilterSection.skuFilter}}" userInput="{{product.sku}}" stepKey="fillProductSkuFilter"/>
<selectOption selector="{{AdminProductGridFilterSection.typeFilter}}" userInput="{{product.type_id}}" stepKey="selectionProductType"/>
<click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFilters"/>
<!--Select first product from grid and open mass action-->
<click selector="{{AdminProductGridSection.productGridCheckboxOnRow('1')}}" stepKey="clickCheckbox"/>
<click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/>
<click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickOption"/>
<waitForPageLoad stepKey="waitForUploadPage"/>
<seeInCurrentUrl url="{{ProductAttributesEditPage.url}}" stepKey="seeAttributePageEditUrl"/>
<!--Update inventory attributes and save-->
<click selector="{{AdminUpdateAttributesAdvancedInventorySection.inventory}}" stepKey="openInvetoryTab"/>
<click selector="{{AdminUpdateAttributesAdvancedInventorySection.changeQty}}" stepKey="uncheckChangeQty"/>
<fillField selector="{{AdminUpdateAttributesAdvancedInventorySection.qty}}" userInput="{{attributes.qty}}" stepKey="fillFieldName"/>
<click selector="{{AdminUpdateAttributesAdvancedInventorySection.changeStockAvailability}}" stepKey="uncheckChangeStockAvailability"/>
<selectOption selector="{{AdminUpdateAttributesAdvancedInventorySection.stockAvailability}}" userInput="{{attributes.stockAvailability}}" stepKey="selectStatus"/>
<click selector="{{AdminUpdateAttributesSection.saveButton}}" stepKey="save"/>
<waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitVisibleSuccessMessage"/>
<see selector="{{AdminMessagesSection.success}}" userInput="Message is added to queue" stepKey="seeSuccessMessage"/>
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPageSecondTime"/>
<waitForPageLoad stepKey="waitForProductGridPage"/>
<conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFiltersAfterMassAction"/>
</actionGroup>
</actionGroups>
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@
<data key="name" unique="suffix">New Bundle Product Name</data>
<data key="description" unique="suffix">This is the description</data>
</entity>
<entity name="UpdateAttributeQtyAndStockToInStock" type="productAttributeMassUpdate">
<data key="qty">10</data>
<data key="stockAvailability">In Stock</data>
</entity>
<entity name="UpdateAttributeQtyAndStockToOutOfStock" type="productAttributeMassUpdate">
<data key="qty">0</data>
<data key="stockAvailability">Out of Stock</data>
</entity>
</entities>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
<section name="AdminUpdateAttributesAdvancedInventorySection">
<element name="inventory" type="button" selector="#attributes_update_tabs_inventory"/>
<element name="changeQty" type="checkbox" selector="#inventory_qty_checkbox"/>
<element name="qty" type="input" selector="#inventory_qty"/>
<element name="changeStockAvailability" type="checkbox" selector="#inventory_stock_availability_checkbox"/>
<element name="stockAvailability" type="select" selector="//select[@name='inventory[is_in_stock]']"/>
</section>
</sections>
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogInventory\Plugin;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\CatalogInventory\Observer\ParentItemProcessorInterface;

/**
* MassUpdate product attribute.
* Around plugin for MassUpdate product attribute via product grid.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class MassUpdateProductAttribute
Expand Down Expand Up @@ -49,6 +55,15 @@ class MassUpdateProductAttribute
*/
private $messageManager;

/**
* @var ParentItemProcessorInterface[]
*/
private $parentItemProcessorPool;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;
/**
* @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor
* @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
Expand All @@ -57,6 +72,8 @@ class MassUpdateProductAttribute
* @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration
* @param \Magento\Catalog\Helper\Product\Edit\Action\Attribute $attributeHelper
* @param \Magento\Framework\Message\ManagerInterface $messageManager
* @param ProductRepositoryInterface $productRepository
* @param ParentItemProcessorInterface[] $parentItemProcessorPool
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
Expand All @@ -66,7 +83,9 @@ public function __construct(
\Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository,
\Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration,
\Magento\Catalog\Helper\Product\Edit\Action\Attribute $attributeHelper,
\Magento\Framework\Message\ManagerInterface $messageManager
\Magento\Framework\Message\ManagerInterface $messageManager,
ProductRepositoryInterface $productRepository,
array $parentItemProcessorPool = []
) {
$this->stockIndexerProcessor = $stockIndexerProcessor;
$this->dataObjectHelper = $dataObjectHelper;
Expand All @@ -75,6 +94,8 @@ public function __construct(
$this->stockConfiguration = $stockConfiguration;
$this->attributeHelper = $attributeHelper;
$this->messageManager = $messageManager;
$this->productRepository = $productRepository;
$this->parentItemProcessorPool = $parentItemProcessorPool;
}

/**
Expand Down Expand Up @@ -145,6 +166,7 @@ private function addConfigSettings($inventoryData)
private function updateInventoryInProducts($productIds, $websiteId, $inventoryData): void
{
foreach ($productIds as $productId) {
$product = $this->productRepository->getById($productId);
$stockItemDo = $this->stockRegistry->getStockItem($productId, $websiteId);
if (!$stockItemDo->getProductId()) {
$inventoryData['product_id'] = $productId;
Expand All @@ -153,7 +175,21 @@ private function updateInventoryInProducts($productIds, $websiteId, $inventoryDa
$this->dataObjectHelper->populateWithArray($stockItemDo, $inventoryData, StockItemInterface::class);
$stockItemDo->setItemId($stockItemId);
$this->stockItemRepository->save($stockItemDo);
$this->processParents($product);
}
$this->stockIndexerProcessor->reindexList($productIds);
}

/**
* Process stock data for parent products
*
* @param ProductInterface $product
* @return void
*/
private function processParents(ProductInterface $product): void
{
foreach ($this->parentItemProcessorPool as $processor) {
$processor->process($product);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function prepareData($collection, $productIds): void
->addAttributeToSelect('samples_title');
// set global scope during export
$this->storeManager->setCurrentStore(Store::DEFAULT_STORE_ID);
foreach ($collection as $product) {
foreach ($productCollection as $product) {
$productLinks = $this->linkRepository->getLinksByProduct($product);
$productSamples = $this->sampleRepository->getSamplesByProduct($product);
$this->downloadableData[$product->getId()] = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\DownloadableImportExport\Test\Unit\Model\Export\Product;

use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
use Magento\Downloadable\Model\LinkRepository;
use Magento\Downloadable\Model\Product\Type as Type;
use Magento\Downloadable\Model\SampleRepository;
use Magento\DownloadableImportExport\Model\Export\RowCustomizer;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

/**
* Class to test Customizes output during export
*/
class RowCustomizerTest extends TestCase
{
/**
* @var LinkRepository|MockObject
*/
private $linkRepository;

/**
* @var SampleRepository|MockObject
*/
private $sampleRepository;

/**
* @var StoreManagerInterface|MockObject
*/
private $storeManager;

/**
* @var RowCustomizer
*/
private $rowCustomizer;

/**
* @inheritdoc
*/
protected function setUp(): void
{
$this->linkRepository = $this->createMock(LinkRepository::class);
$this->sampleRepository = $this->createMock(SampleRepository::class);
$this->storeManager = $this->createMock(StoreManagerInterface::class);

$this->rowCustomizer = new RowCustomizer(
$this->storeManager,
$this->linkRepository,
$this->sampleRepository
);
}

/**
* Test to Prepare downloadable data for export
*/
public function testPrepareData()
{
$productIds = [1, 2, 3];
$collection = $this->createMock(ProductCollection::class);
$collection->expects($this->at(0))
->method('addAttributeToFilter')
->with('entity_id', ['in' => $productIds])
->willReturnSelf();
$collection->expects($this->at(1))
->method('addAttributeToFilter')
->with('type_id', ['eq' => Type::TYPE_DOWNLOADABLE])
->willReturnSelf();
$collection->method('addAttributeToSelect')->willReturnSelf();
$collection->method('getIterator')->willReturn(new \ArrayIterator([]));

$this->storeManager->expects($this->once())
->method('setCurrentStore')
->with(Store::DEFAULT_STORE_ID);

$this->rowCustomizer->prepareData($collection, $productIds);
}
}
Loading

0 comments on commit 0a55921

Please sign in to comment.