<?php declare(strict_types=1);
namespace Shopware\B2B\Cart\BridgePlatform;
use Shopware\B2B\Common\Controller\B2bControllerRedirectException;
use Shopware\B2B\Common\IdValue;
use Shopware\B2B\Contact\Framework\ContactIdentity;
use Shopware\B2B\LineItemList\BridgePlatform\LineItemCheckoutSource;
use Shopware\B2B\LineItemList\Framework\LineItemListService;
use Shopware\B2B\Order\BridgePlatform\AdditionalDataExtension;
use Shopware\B2B\Order\Framework\OrderCheckoutSource;
use Shopware\B2B\Order\Framework\OrderContext;
use Shopware\B2B\Order\Framework\OrderContextRepository;
use Shopware\B2B\Order\Framework\OrderContextService;
use Shopware\B2B\OrderClearance\BridgePlatform\OrderClearanceInquiryMailEvent;
use Shopware\B2B\OrderClearance\Framework\OrderClearanceRepository;
use Shopware\B2B\StoreFrontAuthentication\Framework\AuthenticationService;
use Shopware\B2B\StoreFrontAuthentication\Framework\Identity;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class OrderClearanceCartInterceptor implements EventSubscriberInterface
{
/**
* @var LineItemListService
*/
private $lineItemListService;
/**
* @var OrderContextService
*/
private $orderContextService;
/**
* @var AuthenticationService
*/
private $authenticationService;
/**
* @var OrderClearanceRepository
*/
private $orderClearanceRepository;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var CartService
*/
private $cartService;
/**
* @var ShopCartService
*/
private $shopCartService;
/**
* @var OrderContextRepository
*/
private $orderContextRepository;
/**
* @var TotalPriceCalculationService
*/
private $totalPriceCalculationService;
public function __construct(
AuthenticationService $authenticationService,
LineItemListService $lineItemListService,
OrderContextService $orderContextService,
OrderClearanceRepository $orderClearanceRepository,
EventDispatcherInterface $eventDispatcher,
CartService $cartService,
ShopCartService $shopCartService,
OrderContextRepository $orderContextRepository,
TotalPriceCalculationService $totalPriceCalculationService
) {
$this->authenticationService = $authenticationService;
$this->lineItemListService = $lineItemListService;
$this->orderContextService = $orderContextService;
$this->orderClearanceRepository = $orderClearanceRepository;
$this->eventDispatcher = $eventDispatcher;
$this->cartService = $cartService;
$this->shopCartService = $shopCartService;
$this->orderContextRepository = $orderContextRepository;
$this->totalPriceCalculationService = $totalPriceCalculationService;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array
{
return [CartInterceptEvent::class => 'moveToClearance'];
}
public function moveToClearance(CartInterceptEvent $event): void
{
$identity = $this->authenticationService
->getIdentity();
$context = $event->getContext();
$orderContext = $this->createOrderContext($identity, $event->getCart(), $context);
$this->updateOrderContextWithAdditionalData($orderContext, $context);
$this->orderClearanceRepository
->sendToOrderClearance($orderContext->id, $identity->getOwnershipContext());
$this->sendOrderClearanceInquiryToDebtor($orderContext, $identity, $event->getContext());
$this->shopCartService->clear($event->getContext());
throw new B2bControllerRedirectException('finish', 'b2bcart');
}
/**
* @internal
*/
protected function updateOrderContextWithAdditionalData(
OrderContext $orderContext,
SalesChannelContext $context
): void {
$cart = $this->cartService->getCart($context->getToken(), $context);
/** @var AdditionalDataExtension $additionalData */
$additionalData = $cart->getExtension(AdditionalDataExtension::NAME);
if (!$additionalData) {
return;
}
$orderReference = $additionalData->getOrderReferenceNumber();
$deliveryDate = $additionalData->getRequestedDeliveryDate();
if (!$orderReference && !$deliveryDate) {
return;
}
$orderContext->orderReference = $orderReference;
$orderContext->requestedDeliveryDate = $deliveryDate;
$this->orderContextRepository->updateContext($orderContext);
}
/**
* @internal
*/
protected function createOrderContext(Identity $identity, Cart $cart, SalesChannelContext $salesChannelContext): OrderContext
{
$ownershipContext = $identity->getOwnershipContext();
$list = $this->lineItemListService
->createListThroughCheckoutSource(
$ownershipContext,
new LineItemCheckoutSource($cart)
);
return $this->orderContextService
->createContextThroughCheckoutSource(
$ownershipContext,
$list,
$this->createOrderCheckoutSourceFromCart($cart, $salesChannelContext)
);
}
/**
* @internal
*/
protected function createOrderCheckoutSourceFromCart(Cart $cart, SalesChannelContext $salesChannelContext): OrderCheckoutSource
{
// ToDo set comment and device type
return new OrderCheckoutSource(
IdValue::create($salesChannelContext->getCustomer()->getActiveBillingAddress()->getId()),
IdValue::create($salesChannelContext->getCustomer()->getActiveShippingAddress()->getId()),
IdValue::create($salesChannelContext->getShippingMethod()->getId()),
'',
'',
$this->totalPriceCalculationService->getTotalAmount($cart->getShippingCosts(), $salesChannelContext),
$this->totalPriceCalculationService->getTotalAmountNet($cart->getShippingCosts(), $salesChannelContext),
IdValue::create($salesChannelContext->getPaymentMethod()->getId())
);
}
/**
* @internal
*/
protected function sendOrderClearanceInquiryToDebtor(OrderContext $orderContext, Identity $identity, SalesChannelContext $salesChannelContext): void
{
if (!$identity instanceof ContactIdentity) {
return;
}
$contact = $identity->getEntity();
$debtor = $contact->debtor;
// @todo There is no guarantee that $contact is actually a ContactEntity here!!
$this->eventDispatcher->dispatch(new OrderClearanceInquiryMailEvent(
$contact,
$debtor,
$salesChannelContext,
$orderContext
));
}
}