163 lines
6.8 KiB
PHP
163 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace Stemcell\SubItemProduct\Observer;
|
|
|
|
use Magento\Catalog\Api\ProductRepositoryInterface;
|
|
use Magento\Catalog\Model\ProductType;
|
|
use Magento\CatalogInventory\Api\RegisterProductSaleInterface;
|
|
use Magento\CatalogInventory\Observer\ItemsForReindex;
|
|
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
|
|
use Magento\Framework\Api\FilterBuilder;
|
|
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
|
|
use Magento\Framework\Event\Observer;
|
|
use Magento\Framework\Event\ObserverInterface;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Exception\NoSuchEntityException;
|
|
use Magento\InventoryApi\Api\GetSourceItemsBySkuInterface;
|
|
use Magento\InventoryReservationsApi\Model\AppendReservationsInterface;
|
|
use Magento\InventoryReservationsApi\Model\ReservationBuilderInterface;
|
|
use Magento\InventorySales\Model\ResourceModel\GetAssignedStockIdForWebsite;
|
|
use Magento\InventorySalesApi\Api\Data\SalesEventInterface;
|
|
use Magento\Sales\Model\Order;
|
|
use Psr\Log\LoggerInterface;
|
|
use Stemcell\SubItemProduct\Model\SubItemRepository;
|
|
use \Magento\InventoryApi\Api\SourceItemsSaveInterface;
|
|
use Stemcell\SubItemProduct\Model\ResourceModel\SubItem as SubItemResourceModel;
|
|
|
|
class SubtractSubItemInventory implements ObserverInterface
|
|
{
|
|
protected array $subProductsParent = [];
|
|
const DEFAULT_SOURCE_CODE = 'default';
|
|
|
|
protected array $subItems = [];
|
|
|
|
public function __construct(
|
|
protected GetSourceItemsBySkuInterface $getSourceItemsBySku,
|
|
protected SubItemRepository $subItemRepository,
|
|
protected ProductRepositoryInterface $productRepository,
|
|
protected SearchCriteriaBuilder $searchCriteriaBuilder,
|
|
protected FilterBuilder $filterBuilder,
|
|
protected ReservationBuilderInterface $reservationBuilder,
|
|
protected AppendReservationsInterface $appendReservations,
|
|
protected GetAssignedStockIdForWebsite $getAssignedStockIdForWebsite,
|
|
protected SourceItemsSaveInterface $sourceItemsSave,
|
|
protected LoggerInterface $logger,
|
|
protected SubItemResourceModel $subItemResourceModel,
|
|
){
|
|
}
|
|
|
|
/**
|
|
* @param Order\Item $orderItem
|
|
* @return void
|
|
* @throws LocalizedException
|
|
* @throws NoSuchEntityException
|
|
*/
|
|
protected function getSubItemsFromOrderItem(Order\Item $orderItem)
|
|
{
|
|
$criteria = $this->searchCriteriaBuilder->addFilter(
|
|
$this->filterBuilder->setField('product_id')->setValue($orderItem->getProductId())->create()
|
|
)
|
|
->create();
|
|
|
|
$result = $this->subItemRepository->getList($criteria);
|
|
$this->logger->debug(sprintf('$orderItem product sku %s, id:%d contains %d', $orderItem->getSku(), $orderItem->getProductId(), $result->getTotalCount()));
|
|
foreach ($result->getItems() as $subItem) {
|
|
$this->logger->debug(sprintf(' %s, id:%d contains', $orderItem->getSku(), $orderItem->getProductId()), $subItem->getData());
|
|
$subProduct = $this->productRepository->getById($subItem->getSubProductId());
|
|
if (isset($items[$subItem->getSubProductId()])) {
|
|
$this->subItems[$subItem->getSubProductId()]['qty'] += $orderItem->getQtyOrdered() * intval($subItem->getQuality());
|
|
} else {
|
|
$this->subItems[$subItem->getSubProductId()] = [
|
|
'qty' => $orderItem->getQtyOrdered() * intval($subItem->getQuality()),
|
|
'sku' => $subProduct->getSku(),
|
|
];
|
|
}
|
|
$this->subProductsParent[$subItem->getSubProductId()] = $orderItem->getSku();
|
|
}
|
|
}
|
|
/**
|
|
* @param Order\Item $orderItem
|
|
* @return void
|
|
*/
|
|
protected function getSubItemQtyOrdered(Order\Item $orderItem)
|
|
{
|
|
try {
|
|
$this->getSubItemsFromOrderItem($orderItem);
|
|
$this->logger->debug('$this->subItems: ', $this->subItems);
|
|
$sourceItems = [];
|
|
foreach ($this->subItems as $subItem) {
|
|
$items = $this->getSourceItemsBySku->execute($subItem['sku']);
|
|
foreach ($items as $sourceItem) {
|
|
if ($sourceItem->getSourceCode() === self::DEFAULT_SOURCE_CODE) {
|
|
$this->logger->debug(sprintf('source item %s, product sku: %s, product stock:%f, qty:%d', $sourceItem->getSourceCode(), $subItem['sku'], $sourceItem->getQuantity(), $subItem['qty']));
|
|
$newQty = $sourceItem->getQuantity() - $subItem['qty'];
|
|
$sourceItem->setQuantity($newQty);
|
|
$sourceItems[] = $sourceItem;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (!empty($sourceItems)) {
|
|
$this->sourceItemsSave->execute($sourceItems);
|
|
}
|
|
|
|
} catch (LocalizedException $e) {
|
|
$this->logger->critical('subitem getSubItemQtyOrdered error: '.$e->getMessage(), $e->getTrace());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Order $order
|
|
* @param array $items
|
|
* @return void
|
|
* @throws NoSuchEntityException
|
|
* @throws \Magento\Framework\Exception\CouldNotSaveException
|
|
* @throws \Magento\Framework\Exception\InputException
|
|
* @throws \Magento\Framework\Validation\ValidationException
|
|
*/
|
|
protected function appendReservations(Order $order, array $items)
|
|
{
|
|
$stockId = $this->getAssignedStockIdForWebsite->execute($order->getStore()->getWebsite()->getCode());
|
|
$reservations = [];
|
|
foreach ($items as $subProductId => $item) {
|
|
$reservations[] = $this->reservationBuilder->setSku($item['sku'])
|
|
->setQuantity(-$item['qty'])
|
|
->setStockId($stockId)
|
|
->setMetadata(
|
|
json_encode([
|
|
'event_type'=>SalesEventInterface::EVENT_ORDER_PLACED,
|
|
'object_type'=>SalesEventInterface::OBJECT_TYPE_ORDER,
|
|
'object_id'=>$order->getId(),
|
|
'object_increment_id' => $order->getIncrementId(),
|
|
'comment' => 'sub product of '.$this->subProductsParent[$subProductId],
|
|
])
|
|
)
|
|
->build();
|
|
}
|
|
|
|
$this->appendReservations->execute($reservations);
|
|
}
|
|
|
|
public function execute(Observer $observer)
|
|
{
|
|
/* @var $order Order */
|
|
$order = $observer->getData('order');
|
|
|
|
/* @var $item Order\Item */
|
|
foreach ($order->getAllVisibleItems() as $item) {
|
|
$qty = (int)$item->getQtyOrdered();
|
|
|
|
|
|
try {
|
|
$product = $this->productRepository->get($item->getSku());
|
|
$this->subItemResourceModel->getConnection()->query("
|
|
update subitem_product set stock_qty = stock_qty - (bundle_qty*$qty)
|
|
where product_id={$product->getEntityId()};
|
|
");
|
|
} catch (NoSuchEntityException $e) {
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|