Skip to content

Commit

Permalink
Merge forwardport of #11997 to 2.3-develop branch
Browse files Browse the repository at this point in the history
Applied pull request patch https://github.com/magento/magento2/pull/11997.patch (created by @nmalevanec) based on commit(s):
  1. 0db2b08

Fixed GitHub Issues in 2.3-develop branch:
  - #11941: Invoice for products that use qty decimal rounds down to whole number (reported by @ralbin)
  • Loading branch information
magento-engcom-team authored Jan 24, 2018
2 parents 9aa036d + d5c9eef commit fda37ef
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\CatalogInventory\Observer;

use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

/**
* Add Stock items to product collection.
*/
class AddStockItemsObserver implements ObserverInterface
{
/**
* @var StockItemCriteriaInterfaceFactory
*/
private $criteriaInterfaceFactory;

/**
* @var StockItemRepositoryInterface
*/
private $stockItemRepository;

/**
* @var StockConfigurationInterface
*/
private $stockConfiguration;

/**
* AddStockItemsObserver constructor.
*
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
* @param StockItemRepositoryInterface $stockItemRepository
* @param StockConfigurationInterface $stockConfiguration
*/
public function __construct(
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
StockItemRepositoryInterface $stockItemRepository,
StockConfigurationInterface $stockConfiguration
) {
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
$this->stockItemRepository = $stockItemRepository;
$this->stockConfiguration = $stockConfiguration;
}

/**
* Add stock items to products in collection.
*
* @param Observer $observer
* @return void
*/
public function execute(Observer $observer)
{
/** @var Collection $productCollection */
$productCollection = $observer->getData('collection');
$productIds = array_keys($productCollection->getItems());
$criteria = $this->criteriaInterfaceFactory->create();
$criteria->setProductsFilter($productIds);
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
$stockItemCollection = $this->stockItemRepository->getList($criteria);
foreach ($stockItemCollection->getItems() as $item) {
/** @var Product $product */
$product = $productCollection->getItemById($item->getProductId());
$productExtension = $product->getExtensionAttributes();
$productExtension->setStockItem($item);
$product->setExtensionAttributes($productExtension);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\CatalogInventory\Test\Unit\Observer;

use Magento\Catalog\Api\Data\ProductExtensionInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
use Magento\CatalogInventory\Api\Data\StockItemCollectionInterface;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\CatalogInventory\Api\StockItemCriteriaInterface;
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
use Magento\CatalogInventory\Observer\AddStockItemsObserver;
use Magento\Framework\Event\Observer;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\TestCase;

class AddStockItemsObserverTest extends TestCase
{
/**
* Test subject.
*
* @var AddStockItemsObserver
*/
private $subject;
/**
* @var StockItemCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
*/
private $criteriaInterfaceFactoryMock;

/**
* @var StockItemRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $stockItemRepositoryMock;

/**
* @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $stockConfigurationMock;

/**
* @inheritdoc
*/
protected function setUp()
{
$objectManager = new ObjectManager($this);
$this->criteriaInterfaceFactoryMock = $this->getMockBuilder(StockItemCriteriaInterfaceFactory::class)
->setMethods(['create'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->stockItemRepositoryMock = $this->getMockBuilder(StockItemRepositoryInterface::class)
->setMethods(['getList'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class)
->setMethods(['getDefaultScopeId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->subject = $objectManager->getObject(
AddStockItemsObserver::class,
[
'criteriaInterfaceFactory' => $this->criteriaInterfaceFactoryMock,
'stockItemRepository' => $this->stockItemRepositoryMock,
'stockConfiguration' => $this->stockConfigurationMock
]
);
}

/**
* Test AddStockItemsObserver::execute() add stock item to product as extension attribute.
*/
public function testExecute()
{
$productId = 1;
$defaultScopeId = 0;

$criteria = $this->getMockBuilder(StockItemCriteriaInterface::class)
->setMethods(['setProductsFilter', 'setScopeFilter'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$criteria->expects(self::once())
->method('setProductsFilter')
->with(self::identicalTo([$productId]))
->willReturn(true);
$criteria->expects(self::once())
->method('setScopeFilter')
->with(self::identicalTo($defaultScopeId))
->willReturn(true);

$this->criteriaInterfaceFactoryMock->expects(self::once())
->method('create')
->willReturn($criteria);
$stockItemCollection = $this->getMockBuilder(StockItemCollectionInterface::class)
->setMethods(['getItems'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$stockItem = $this->getMockBuilder(StockItemInterface::class)
->setMethods(['getProductId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$stockItem->expects(self::once())
->method('getProductId')
->willReturn($productId);

$stockItemCollection->expects(self::once())
->method('getItems')
->willReturn([$stockItem]);

$this->stockItemRepositoryMock->expects(self::once())
->method('getList')
->with(self::identicalTo($criteria))
->willReturn($stockItemCollection);

$this->stockConfigurationMock->expects(self::once())
->method('getDefaultScopeId')
->willReturn($defaultScopeId);

$productExtension = $this->getMockBuilder(ProductExtensionInterface::class)
->setMethods(['setStockItem'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$productExtension->expects(self::once())
->method('setStockItem')
->with(self::identicalTo($stockItem));

$product = $this->getMockBuilder(Product::class)
->disableOriginalConstructor()
->getMock();
$product->expects(self::once())
->method('getExtensionAttributes')
->willReturn($productExtension);
$product->expects(self::once())
->method('setExtensionAttributes')
->with(self::identicalTo($productExtension))
->willReturnSelf();

/** @var ProductCollection|\PHPUnit_Framework_MockObject_MockObject $productCollection */
$productCollection = $this->getMockBuilder(ProductCollection::class)
->disableOriginalConstructor()
->getMock();
$productCollection->expects(self::once())
->method('getItems')
->willReturn([$productId => $product]);
$productCollection->expects(self::once())
->method('getItemById')
->with(self::identicalTo($productId))
->willReturn($product);

/** @var Observer|\PHPUnit_Framework_MockObject_MockObject $observer */
$observer = $this->getMockBuilder(Observer::class)
->disableOriginalConstructor()
->getMock();
$observer->expects(self::once())
->method('getData')
->with('collection')
->willReturn($productCollection);

$this->subject->execute($observer);
}
}
3 changes: 3 additions & 0 deletions app/code/Magento/CatalogInventory/etc/events.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@
<event name="admin_system_config_changed_section_cataloginventory">
<observer name="inventory" instance="Magento\CatalogInventory\Observer\UpdateItemsStockUponConfigChangeObserver"/>
</event>
<event name="sales_quote_item_collection_products_after_load">
<observer name="add_stock_items" instance="Magento\CatalogInventory\Observer\AddStockItemsObserver"/>
</event>
</config>
Loading

0 comments on commit fda37ef

Please sign in to comment.