<?php declare(strict_types=1);
namespace Shopware\B2B\InStock\BridgePlatform;
use Shopware\B2B\Common\IdValue;
use Shopware\B2B\InStock\Framework\InStockRepository;
use Shopware\B2B\InStock\Framework\InStockSearchStruct;
use Shopware\B2B\StoreFrontAuthentication\Framework\AuthenticationService;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function array_flip;
class InStockCheckoutSubscriber implements EventSubscriberInterface
{
/**
* @var AuthenticationService
*/
private $authenticationService;
/**
* @var InStockRepository
*/
private $inStockRepository;
/**
* @var InStockBridgeRepository
*/
private $inStockBridgeRepository;
public function __construct(
AuthenticationService $authenticationService,
InStockRepository $inStockRepository,
InStockBridgeRepository $inStockBridgeRepository
) {
$this->authenticationService = $authenticationService;
$this->inStockRepository = $inStockRepository;
$this->inStockBridgeRepository = $inStockBridgeRepository;
}
public static function getSubscribedEvents(): array
{
return [
CheckoutOrderPlacedEvent::class => 'updateInStockAfterOrderPlaced',
];
}
public function updateInStockAfterOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
if (!$this->authenticationService->isB2b()) {
return;
}
/** @var OrderLineItemCollection $lineItems */
$lineItems = $event->getOrder()->getLineItems();
$productIds = $lineItems->fmap(function (OrderLineItemEntity $lineItem) {
if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
return null;
}
return $lineItem->getReferencedId();
});
$inStocks = $this->inStockBridgeRepository->fetchInStocksByProductIds(
IdValue::fromHexToBytesList($productIds),
$this->authenticationService->getIdentity(),
new InStockSearchStruct()
);
$lineItemIds = array_flip($productIds);
$matchedInStocks = [];
foreach ($inStocks as $productId => $inStock) {
$lineItem = $lineItems->get($lineItemIds[$productId]);
$inStock->inStock -= $lineItem->getQuantity();
$matchedInStocks[] = $inStock;
}
if (!$matchedInStocks) {
return;
}
$this->inStockRepository->updateMultipleInStocks($matchedInStocks);
}
}