Files
stemcell/app/code/Stemcell/SubItemProduct/Observer/SubtractSubItemInventory1.php
T
2026-09-15 10:26:34 +08:00

114 lines
4.7 KiB
PHP

<?php
namespace Stemcell\SubItemProduct\Observer;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\CatalogInventory\Api\RegisterProductSaleInterface;
use Magento\CatalogInventory\Observer\ItemsForReindex;
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\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;
class SubtractSubItemInventory1 implements ObserverInterface
{
private array $subProductsParent = [];
public function __construct(
private RegisterProductSaleInterface $registerProductSale,
private SubItemRepository $subItemRepository,
private ProductRepositoryInterface $productRepository,
private ItemsForReindex $itemsForReindex,
private SearchCriteriaBuilder $searchCriteriaBuilder,
private FilterBuilder $filterBuilder,
private ReservationBuilderInterface $reservationBuilder,
private AppendReservationsInterface $appendReservations,
private GetAssignedStockIdForWebsite $getAssignedStockIdForWebsite,
private LoggerInterface $logger
){
}
protected function getSubItemQtyOrdered(Order\Item $orderItem, array &$items)
{
$criteria = $this->searchCriteriaBuilder->addFilter(
$this->filterBuilder->setField('product_id')->setValue($orderItem->getProductId())->create()
)
->create();
try {
$result = $this->subItemRepository->getList($criteria);
foreach ($result->getItems() as $subItem) {
if(isset($items[$subItem->getSubProductId()])) {
$items[$subItem->getSubProductId()] += $orderItem->getRowTotal() * $subItem->getQuality();
} else {
$items[$subItem->getSubProductId()] = $orderItem->getRowTotal() * $subItem->getQuality();
}
$this->subProductsParent[$subItem->getSubProductId()] = $orderItem->getSku();
}
} catch (LocalizedException $e) {
}
}
/**
* @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 => $quantity) {
$product = $this->productRepository->getById($subProductId);
$reservations[] = $this->reservationBuilder->setSku($product->getSku())
->setQuantity(-$quantity)
->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');
$items = [];
foreach ($order->getItems() as $item) {
$this->getSubItemQtyOrdered($item, $items);
}
$this->logger->debug('subtract sub item inventory, items:', $items);
try {
$itemsForReindex = $this->registerProductSale->registerProductsSale($items, $order->getStore()->getWebsiteId());
if (count($itemsForReindex)) {
$this->itemsForReindex->setItems($itemsForReindex);
}
$this->appendReservations($order, $items);
} catch (\Exception $e) {
$this->logger->critical('subtract sub item inventory error, ', $e->getTrace());
}
}
}