<?php
namespace App\EventListener\Stock;
use App\Atd\Domain\Response\BookingSummary\BookingSummary;
use App\Atd\Domain\Response\ResponseWrapper;
use App\Atd\Supplier\Atd\OrderLog\Event\OrderLogEvent;
use App\Atd\Supplier\Atd\OrderLog\Service\OrderLogService;
use App\Atd\Supplier\Atd\Stock\Service\StockService;
use App\Event\Stock\StockTriggerEvent;
use App\Service\ProviderFactoryService;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class StockSubscriber implements EventSubscriberInterface
{
public const STOCK_SERVICE_TYPE = 'stock';
public const ORDER_SERVICE_TYPE = 'order';
private StockService $stockService;
/**
* @throws \Exception
*/
public function __construct(
private readonly LoggerInterface $logger,
private readonly OrderLogService $orderLogService,
private readonly ProviderFactoryService $providerFactory,
) {
$this->stockService = $this->providerFactory->factory('atd', self::STOCK_SERVICE_TYPE);
}
public static function getSubscribedEvents(): array
{
return [
StockTriggerEvent::class => 'handleTrigger',
];
}
/**
* @throws \Throwable
*/
public function handleTrigger(StockTriggerEvent $event): void
{
$this->doStock($event->getResponseWrapper(), $event->getOrderId());
}
/**
* @throws \Exception
*/
private function doStock(ResponseWrapper $bookingResponse, string $orderId): void
{
$orderService = $this->providerFactory->factory('atd', self::ORDER_SERVICE_TYPE);
$order = $orderService->getOrder($orderId);
try {
$stockResponse = $this->stockService->doRequest([
'order' => $order,
'bookingResponse' => $bookingResponse,
], null);
} catch (\Exception $e) {
$this->logBookingSummary($orderId, $bookingResponse);
// Don't re-throw as we don't want the booking response to be blocked
}
if (!empty($stockResponse['errors'])) {
foreach ($stockResponse['errors'] as $error) {
$this->logger->error($error);
}
} else {
$this->logger->info('Stock Updated!');
}
}
/**
* @todo - refactor to an Dispatch / Event
*/
private function logBookingSummary(string $orderId, ResponseWrapper $bookingResponse): void
{
try {
$bookingSummary = BookingSummary::create($orderId, $bookingResponse);
$orderLogEvent = new OrderLogEvent($orderId, $bookingSummary->toString());
$this->orderLogService->write($orderLogEvent);
} catch (\Exception $e) {
$this->logger->error('When attempting to write a BookingSummary to the Order Log: '.$e->getMessage());
}
}
}