<?php
namespace CioApprovalThreshold\Controller;
use CioApprovalThreshold\Definition\Customer\CustomerApprovalThresholdEntity;
use CioApprovalThreshold\States\ApprovalStates;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Order\OrderDefinition;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\StateMachine\StateMachineRegistry;
use Shopware\Core\System\StateMachine\Transition;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Storefront\Page\GenericPageLoader;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Framework\Context;
class CustomerProfileController extends StorefrontController
{
private StateMachineRegistry $stateMachineRegistry;
private GenericPageLoader $genericPageLoader;
public function __construct(StateMachineRegistry $stateMachineRegistry, GenericPageLoader $genericPageLoader)
{
$this->stateMachineRegistry = $stateMachineRegistry;
$this->genericPageLoader = $genericPageLoader;
}
/**
* @Route("/account/approvalthreshold", name="frontend.account.cioapprovalthreshold.page", methods={"GET"}, defaults={"_routeScope"={"storefront"}})
* @param SalesChannelContext $context
* @return Response
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function index(Request $request, SalesChannelContext $context): Response
{
if (!$context->getCustomer() instanceof CustomerEntity) {
throw new CustomerNotLoggedInException();
}
/** @var EntityRepository $customerRepository */
$customerRepository = $this->container->get('customer.repository');
// all customers with a release limit over 0 points are qualified as default release customer
$criteria = new Criteria();
$criteria->addFilter(new RangeFilter('approvalThresholdExtension.releaseThreshold', [
RangeFilter::GT => 0
]));
$possibleDefaultReleaser = $customerRepository->search($criteria, $context->getContext());
/** @var CustomerApprovalThresholdEntity|null $customerThreshold */
$customerThreshold = $context->getCustomer()->getExtension('approvalThresholdExtension');
return $this->renderStorefront('@CioApprovalThreshold/storefront/page/account/approval_threshold.html.twig', [
'page' => $this->genericPageLoader->load($request, $context),
'customerApprovalThreshold' => $customerThreshold?->getReleaseThreshold() ?? 0,
'customerDefaultReleaser' => $customerThreshold?->getDefaultReleaseCustomerId(),
'possibleDefaultReleaser' => $possibleDefaultReleaser->getElements()
]);
}
/**
* @Route("/account/approvalthreshold", name="frontend.account.cioapprovalthreshold.save", methods={"POST"}, defaults={"_routeScope"={"storefront"}})
* @param Request $request
* @param SalesChannelContext $context
* @return RedirectResponse
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function save(Request $request, SalesChannelContext $context): RedirectResponse
{
if (!$context->getCustomer() instanceof CustomerEntity) {
throw new CustomerNotLoggedInException();
}
$releaserId = $request->request->get('defaultReleaseCustomer');
/** @var EntityRepository $customerRepository */
$customerRepository = $this->container->get('customer.repository');
/** @var Session $session */
$session = $request->getSession();
if (!is_string($releaserId) || !Uuid::isValid($releaserId)) {
$session->getFlashBag()->add('danger', $this->trans('account.cioAccountApproval.errorIncorrectCustomerId'));
return $this->redirectToRoute('frontend.account.cioapprovalthreshold.page');
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $releaserId));
$releaser = $customerRepository->search($criteria, $context->getContext())->first();
if (!$releaser instanceof CustomerEntity) {
$session->getFlashBag()->add('danger', $this->trans('account.cioAccountApproval.errorIncorrectCustomerId'));
return $this->redirectToRoute('frontend.account.cioapprovalthreshold.page');
}
$customerRepository->update([
[
'id' => $context->getCustomer()->getId(),
'approvalThresholdExtension' => [
'defaultReleaseCustomerId' => $releaser->getId()
]
]
], $context->getContext());
$session->getFlashBag()->add('success', $this->trans('account.cioAccountApproval.messageSaveSuccessfully'));
return $this->redirectToRoute('frontend.account.cioapprovalthreshold.page');
}
/**
* Profile page where the customer can check the orders that are waiting for approval by the logged in customer.
* @Route("/account/openapprovalorders", name="frontend.account.openapprovalorders.page", methods={"GET"}, defaults={"_routeScope"={"storefront"}})
* @param SalesChannelContext $context
* @return Response
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function openApprovalOrders(SalesChannelContext $context): Response
{
if (!$context->getCustomer() instanceof CustomerEntity) {
throw new CustomerNotLoggedInException();
}
/** @var EntityRepository $orderRepository */
$orderRepository = $this->container->get('order.repository');
// all customers with a release limit over 0 points are qualified as default release customer
$criteria = new Criteria();
$criteria->addAssociation('stateMachineState');
$criteria->addAssociation('approvalThresholdExtension');
$criteria->addFilter(new EqualsFilter('stateMachineState.technicalName', ApprovalStates::STATE_OPEN_APPROVAL_REQUEST));
$criteria->addFilter(new EqualsFilter('approvalThresholdExtension.selectedReleaseCustomerId', $context->getCustomer()->getId()));
$criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
$openOrders = $orderRepository->search($criteria, $context->getContext());
return $this->renderStorefront('@CioApprovalThreshold/storefront/page/account/open_approval_orders.html.twig', [
'openOrders' => $openOrders
]);
}
/**
* @Route("/account/approvalthreshold/{orderId}/request/cancel", name="frontend.account.cioapprovalthreshold.request.cancel", methods={"GET"}, defaults={"_routeScope"={"storefront"}})
* @param SalesChannelContext $context
* @return Response
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function cancelRequest(string $orderId, SalesChannelContext $context): Response
{
if (!$context->getCustomer() instanceof CustomerEntity) {
throw new CustomerNotLoggedInException();
}
/** @var EntityRepository $orderRepository */
$orderRepository = $this->container->get('order.repository');
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('lineItems');
$criteria->addAssociation('orderCustomer');
$criteria->addFilter(new EqualsFilter('orderCustomer.customerNumber', $context->getCustomer()->getCustomerNumber()));
$criteria->addFilter(new EqualsFilter('stateMachineState.technicalName', ApprovalStates::STATE_OPEN_APPROVAL_REQUEST));
$order = $orderRepository->search($criteria, $context->getContext())->first();
if ($order instanceof OrderEntity) {
$this->stateMachineRegistry->transition(
new Transition(
OrderDefinition::ENTITY_NAME,
$order->getId(),
ApprovalStates::CANCEL_REQUEST_AND_STORNO_ORDER_TRANSITION_NAME,
'stateId'
),
$context->getContext()
);
return $this->renderStorefront('@CioApprovalThreshold/storefront/page/account/cancel_approval_request.html.twig', [
'order' => $order,
]);
}
return $this->redirectToRoute('frontend.account.order.page');
}
}