<?php
namespace App\EventSubscribers\Main;
use App\Entity\Main\AffiliateNotificationConfig;
use App\Entity\Main\BillingAccount;
use App\Entity\Main\RebillManager;
use App\Entity\Main\Site;
use App\Entity\Main\SiteConfig;
use App\Entity\Main\UserSettings;
use App\Events\Main\Order\OrderAcceptedEvent;
use App\Events\Main\Order\OrderFailedCheckedEvent;
use App\Events\Main\Order\OrderLockedEvent;
use App\Events\Main\Order\OrderPaidByClientEvent;
use App\Services\BillingManager;
use App\Services\CartManager;
use App\Services\EmailManager;
use App\Services\ShippingManager;
use App\Services\AffiliateNotificationManager;
use App\Services\MailingManager;
use App\Services\NudgifyManager;
use App\Services\SiteManager;
use App\Services\TransactionManager;
use App\Services\UserManager;
use App\Tools\ReviewsSystem\AvisVerifies;
use App\Tools\ShortId;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
/**
* Class OrderSubscriber
* @package App\EventSubscribers\Main
*/
class OrderSubscriber implements EventSubscriberInterface
{
const
ORDER_ACCEPTED = 'order.accepted',
ORDER_LOCKED = 'order.locked',
ORDER_PAID_BY_CLIENT = 'order.paid_by_client',
CHECKED_FOR_FAILED_ORDER = 'checked_for_failed_order';
/**
* @var EmailManager
*/
private $emailFactory;
/**
* @var ShortId
*/
private $shortId;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var CartManager
*/
private $cartFactory;
/**
* @var ShippingManager
*/
private $shippingFactory;
/**
* @var UserManager
*/
private $userManager;
/**
* @var AffiliateNotificationManager
*/
private $affiliateNotificationManager;
/**
* @var TransactionManager
*/
private $transactionManager;
/**
* @var AvisVerifies
*/
private $avisVerifies;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var SiteManager
*/
private $siteManager;
private $avEnabled;
private $environment;
/**
* @var RouterInterface
*/
private $router;
/**
* @var BillingManager
*/
private $billingFactory;
private NudgifyManager $nudgifyManager;
private array $nudgifyConfig;
private MailingManager $mailingManager;
/**
* CartSubscriber constructor.
* @param EmailManager $emailFactory
* @param ShortId $shortId
* @param EntityManagerInterface $entityManager
* @param CartManager $cartFactory
* @param ShippingManager $shippingFactory
* @param UserManager $userManager
* @param AffiliateNotificationManager $affiliateNotificationManager
* @param TransactionManager $transactionManager
* @param AvisVerifies $avisVerifies
* @param SiteManager $siteManager
* @param LoggerInterface $logger
* @param $environment
* @param RouterInterface $router
* @throws \Exception
*/
public function __construct(
EmailManager $emailFactory,
ShortId $shortId,
EntityManagerInterface $entityManager,
CartManager $cartFactory,
ShippingManager $shippingFactory,
UserManager $userManager,
AffiliateNotificationManager $affiliateNotificationManager,
TransactionManager $transactionManager,
AvisVerifies $avisVerifies,
SiteManager $siteManager,
LoggerInterface $logger,
$environment,
RouterInterface $router,
BillingManager $billingFactory,
NudgifyManager $nudgifyManager,
MailingManager $mailingManager
) {
$this->emailFactory = $emailFactory;
$this->shortId = $shortId;
$this->entityManager = $entityManager;
$this->cartFactory = $cartFactory;
$this->shippingFactory = $shippingFactory;
$this->userManager = $userManager;
$this->affiliateNotificationManager = $affiliateNotificationManager;
$this->transactionManager = $transactionManager;
$this->avisVerifies = $avisVerifies;
$this->logger = $logger;
$this->siteManager = $siteManager;
$this->avEnabled = $this->siteManager->getConfigParam(SiteConfig::AVIS_VERIFIES_NAME)->getValue();
$this->environment = $environment;
$this->router = $router;
$this->billingFactory = $billingFactory;
$this->nudgifyManager = $nudgifyManager;
$this->nudgifyConfig = $this->siteManager->getYamlConfigParameter('nudgify');
$this->mailingManager = $mailingManager;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return array(
self::ORDER_ACCEPTED => "orderAccepted",
self::ORDER_PAID_BY_CLIENT => "orderPaidByClient",
self::ORDER_LOCKED => "orderLocked",
self::CHECKED_FOR_FAILED_ORDER => "checkedForFailedOrder",
);
}
/**
* @param OrderLockedEvent $event
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax
* @throws \Exception
*/
public function orderLocked(OrderLockedEvent $event)
{
// NOTE : This is now where we send the email of the accepted order.
$cart = $event->getCart();
$user = $cart->getUser();
// Now the coaching is being sent from here with the receipt.
if ($cart->getSite()->isCoachingSite()) {
$shippingApi = $this->shippingFactory->getShippingApiForElectronicProduct($cart);
$credentials = $shippingApi->getCredentialsForCoaching($cart);
$this->emailFactory->sendCoachingSitePurchaseEmail($user, $credentials);
// we need to stop the rebill manager as merkav won't do it.
$this->billingFactory->stopRebillManager($cart->getRebillManagers()[0], RebillManager::CANCEL_ONE_SHOT);
// we want to mark the order as delivered.
try {
$this->cartFactory->transitState($cart, 'shippingAwaiting');
$this->cartFactory->transitState($cart, 'shippingDelivery');
$this->cartFactory->transitState($cart, 'shipped');
} catch (\Exception $e) {
$this->logger->critical('Could not change status of a coaching cart. => ' . $cart->getCartId());
}
} elseif ($this->cartFactory->hasCoaching($cart)) {
// here we need to put the new email to send :)
$shippingApi = $this->shippingFactory->getShippingApiForElectronicProduct($cart);
if (null == $shippingApi) {
throw new \LogicException("Can't get shipping api for Electronic product to create email");
}
$credentials = $shippingApi->getCredentialsForCoaching($cart);
$this->emailFactory->sendPurchasedCombo(
$this->shortId->encode($cart->getCartId()),
$cart,
$this->cartFactory->computeCartTotal($cart),
$credentials
);
} else {
$this->emailFactory->sendPurchasedSummary(
$this->shortId->encode($cart->getCartId()),
$cart,
$this->cartFactory->computeCartTotal($cart)
);
}
// We need to create a call to contact this user in 10 days.
if ($this->userManager->userCanBeCalled($user) && !$cart->getSite()->isCoachingSite()) {
$this->userManager->createCallForUser($user, $cart);
}
// queue ordered related scenarios.
$this->mailingManager->queueOrderRelatedScenarios($cart);
// if Avis Verifies is enabled we send order info to the system.
if ($this->avEnabled &&
!$cart->getSite()->isCoachingSite()
&& 'prod' == $this->environment
&& $this->userManager->userCanGiveFeedback($user)
) {
$orderInfo = $this->cartFactory->getOrderInfoFromCartForAvisVerifie($cart, $this->router);
if (!empty($orderInfo)) {
try {
$this->avisVerifies->sendOrderInfo($orderInfo);
} catch (\Exception $e) {
$this->logger->error("We could not send Cart info (cart: " . $cart->getCartId() . ") to the Avis Verifies sytem. Error: " . $e->getMessage());
}
}
}
}
/**
* @param OrderAcceptedEvent $event
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax
*/
public function orderAccepted(OrderAcceptedEvent $event)
{
// NOTE : Here now we send an 'order received email" but it doesn't contain anymore the list of purchases as
// the customer can now add some upsells :)
$this->pushToNudgifyApi($event);
$this->emailFactory->sendOrderReceivedEmail($event->getCart(), $event->getCart()->getEncodedId($this->shortId));
}
/**
* @param OrderPaidByClientEvent $event
*/
public function orderPaidByClient(OrderPaidByClientEvent $event)
{
$cart = $event->getCart();
if (!$cart->getSite()->isCoachingSite()) {
$this->affiliateNotificationManager->addNotification($cart->getTracking(), $cart, AffiliateNotificationConfig::PURCHASE_OVER);
}
}
/**
* @param OrderFailedCheckedEvent $event
*/
public function checkedForFailedOrder(OrderFailedCheckedEvent $event)
{
$cart = $event->getCart();
$user = $cart->getUser();
$request = $event->getRequest();
//allow the user to use PayPal.
$userSettings = $user->getSettings();
$userSettings[UserSettings::PAYPAL_ALLOWED] = true;
$userSettings[UserSettings::PAYPAL_NO_LIMIT] = true;
$user->setSettings($userSettings);
$this->entityManager->flush();
//keep the cart in the session.
$session = $request->getSession();
$session->set('currentCartId', $cart->getCartId());
$session->set('usePayPalMessage', true);
$session->remove(CartManager::CHECK_FAILED_PURCHASE_KEY);
$session->remove(CartManager::DISCOUNT_CODE_KEY);
}
/**
* @param OrderAcceptedEvent $event
* @throws \ErrorException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function pushToNudgifyApi(OrderAcceptedEvent $event)
{
$cart = $event->getCart();
$site = $cart->getSite();
/** @var Site $site */
if ('it' === $cart->getUser()->getUserLocale()) {
$locale = $cart->getUser()->getUserLocale();
} elseif(isset($site->getProperties()['translation']) && isset($site->getProperties()['translation']['locale']) && 'it' === $site->getProperties()['translation']['locale']) {
$locale = $site->getProperties()['translation']['locale'];
} else {
$locale = 'fr';
}
if (true === $this->nudgifyConfig[$locale]['enabled'] && $cart->getPaymentTransaction()->getBillingAccount()->getBillingAccountType() !== BillingAccount::BILLING_ACCOUNT_TYPE_DUMMY) {
$this->nudgifyManager->pushToApiForPurchaseNudges($cart, $this->nudgifyConfig, $locale);
}
}
}