<?php
namespace Twigel\BonusProgram\Subscriber;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Twigel\BonusProgram\Core\Content\TwigelOrderStatus\TwigelOrderStatusEntity;
use Twigel\BonusProgram\Service\TwigelCustomerOrderService;
class OrderDelete implements EventSubscriberInterface
{
/** @var EntityRepository */
private $orderStatusRepository;
/** @var EntityRepository */
private $orderRepository;
/** @var EntityRepository */
private $customerRepository;
/** @var SystemConfigService */
private $config;
/** @var EntityRepository */
private $orderCustomerRepository;
/** @var EntityRepository */
private $customerAccountRepository;
/** @var EntityRepository */
private $twigelStatusRepository;
public function __construct(
EntityRepository $orderStatusRepository,
EntityRepository $orderRepository,
EntityRepository $customerRepository,
SystemConfigService $config,
EntityRepository $orderCustomerRepository,
EntityRepository $customerAccountRepository,
EntityRepository $twigelStatusRepository
)
{
$this->orderStatusRepository = $orderStatusRepository;
$this->orderRepository = $orderRepository;
$this->customerRepository = $customerRepository;
$this->config = $config;
$this->orderCustomerRepository = $orderCustomerRepository;
$this->customerAccountRepository = $customerAccountRepository;
$this->twigelStatusRepository = $twigelStatusRepository;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
OrderEvents::ORDER_DELETED_EVENT => 'deleteOrder'
];
}
/**
* On order delete check customer turnOver and set group for customer
* @param EntityWrittenEvent $event
*/
public function deleteOrder(EntityWrittenEvent $event)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('orderId', null));
$orderStatus = $this->orderStatusRepository->search($criteria, Context::createDefaultContext())->getElements();
/** @var TwigelOrderStatusEntity $item */
foreach ($orderStatus as $item) {
$customerId = $item->getCustomerId();
$status = self::getCustomerTurnOver($customerId);
self::checkCustomerGroup($status, $customerId);
self::checkCustomerAccount($customerId, $item->getBonusAmount());
$this->orderStatusRepository->delete([
[
'id' => $item->getId()
]
], Context::createDefaultContext());
}
}
/**
* Return customer status based on his turnOver
* @param $customerId
* @return string
*/
private function getCustomerTurnOver($customerId): string
{
$service = new TwigelCustomerOrderService($this->orderCustomerRepository);
return $service->countTurnOver($customerId);
}
private function checkCustomerGroup($status, $customerId)
{
$criteria = new Criteria([$customerId]);
/** @var CustomerEntity $customer */
$customer = $this->customerRepository->search($criteria, Context::createDefaultContext())->first();
if ($status){
$statusGroupId = $this->config->get("TwigelBonusProgram")['config'][TwigelCustomerOrderService::CONFIG_CUSTOMER_GROUPS[$status]];
}else{
$statusGroupId = Defaults::FALLBACK_CUSTOMER_GROUP;
}
if ($statusGroupId !== $customer->getGroupId()) {
$this->customerRepository->update([
[
'id' => $customerId,
'groupId' => $statusGroupId
]
], Context::createDefaultContext());
}
}
private function checkCustomerAccount($customerId, $bonusAmount)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customerId', $customerId));
$customerAccount = $this->customerAccountRepository->search($criteria, Context::createDefaultContext())->first();
if (!$customerAccount) {
return null;
}
$status = self::getCustomerStatusId($customerId, Context::createDefaultContext());
$update = [
'id' => $customerAccount->getId(),
'bonusAmount' => $customerAccount->getBonusAmount() - (int)$bonusAmount
];
if ($status){
$update['statusId'] = $status->getId();
}else{
$update['statusId'] = null;
}
$this->customerAccountRepository->update([$update], Context::createDefaultContext());
}
private function getCustomerStatusId($customerId, Context $context)
{
$status = self::getCustomerStatus($customerId);
if ($status['turnOver']) {
$customerGroupId = $this->config->get('TwigelBonusProgram')['config'][TwigelCustomerOrderService::CONFIG_CUSTOMER_GROUPS[$status['turnOver']]];
$statusCriteria = new Criteria();
$statusCriteria->addFilter(new EqualsFilter('customerGroupId', $customerGroupId));
return $this->twigelStatusRepository->search($statusCriteria, $context)->first();
} else {
return null;
}
}
private function getCustomerStatus($customerId)
{
$service = new TwigelCustomerOrderService($this->orderCustomerRepository);
return [
'turnOver' => $service->countTurnOver($customerId),
'amountOfOrders' => $service->countOrdersOfCustomer($customerId)
];
}
}