<?php
namespace App\Controller\GroupSessionController;
use App\Entity\Child;
use App\Entity\Gender;
use App\Entity\Session;
use App\Entity\SessionOrder;
use App\Entity\StripePlanForGroup;
use App\Entity\Subject;
use App\Entity\User;
use App\Notification\EmailNotification;
use App\Notification\SlackClient;
use App\Order\OrderHelper;
use App\Repository\DiscountRepository;
use App\Repository\HolidayRepository;
use App\Repository\LevelTestRepository;
use App\Repository\SessionRegistrationDateRepository;
use App\Repository\SessionRepository;
use App\Repository\StripePlanForGroupRepository;
use App\Repository\SubjectRepository;
use App\Service\ActiveCampaignHelper;
use App\Service\Currency\CurrencyChangeService;
use App\StripeClient;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Stripe\Invoice;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session as SessionSymfo;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/session")
*/
class UserGroupSessionController extends AbstractController
{
private $em;
private $stripeClient;
private $emailNotification;
private $slackClient;
private $activeCampaignHelper;
public function __construct(EntityManagerInterface $em, StripeClient $stripeClient, EmailNotification $emailNotification, SlackClient $slackClient,
ActiveCampaignHelper $activeCampaignHelper
) {
$this->em = $em;
$this->stripeClient = $stripeClient;
$this->emailNotification = $emailNotification;
$this->slackClient = $slackClient;
$this->activeCampaignHelper = $activeCampaignHelper;
}
//Voir
/**
* @Route("/{gender}/{tag}", name="session_index", defaults={"tag": "alKaamil"}, methods={"GET"})
* @ParamConverter("gender", options={"mapping": {"gender" : "name"}})
* @param Gender $gender
* @param $tag
* @param SubjectRepository $subjectRepository
* @param SessionRepository $sessionRepository
* @param HolidayRepository $holidayRepository
* @param SessionRegistrationDateRepository $sessionRegistrationDateRepository
* @param LevelTestRepository $levelTestRepository
*
* @return Response
*/
public function index(Gender $gender, $tag, SubjectRepository $subjectRepository, SessionRepository $sessionRepository, HolidayRepository $holidayRepository,
SessionRegistrationDateRepository $sessionRegistrationDateRepository, LevelTestRepository $levelTestRepository, Request $request,
DiscountRepository $discountRepository
): Response {
$parameter = $request->query->get('d');
$discount = $discountRepository->findOneBy([
'urlParameter' => $parameter,
]);
$subject = $subjectRepository->findOneBy([
'tagName' => $tag,
]);
if ($discount) {
if ($discount->getSubject() == $subject) {
$isDiscount = true;
$discountAmount = $discount->getAmount();
$discountType = $discount->getType();
} else {
$isDiscount = false;
$discountAmount = 0;
$discountType = null;
}
} else {
$isDiscount = false;
$discountAmount = 0;
$discountType = null;
}
if ( ! $subject) {
$this->addFlash('error', "Le programme demandé n'existe pas");
return $this->redirectToRoute('session_index', [
'gender' => $gender,
'_locale' => $request->getLocale(),
]);
}
$sessions = $sessionRepository->openSessionByOrderSubjectGender(
$subject->getTagName(),
$gender->getName()
);
$holidays = $holidayRepository->findAll();
$registrationDate = $sessionRegistrationDateRepository->findOneBy([
'subject' => $subject,
]);
$levelTestInfo = $levelTestRepository->findOneBy([
'type' => "info",
'subject' => $subject,
]);
return $this->render('session/index.html.twig', [
'sessions' => $sessions,
'gender' => $gender,
'local' => $this->getParameter('locale'),
'holidays' => $holidays,
'subject' => $subject,
'registrationDate' => $registrationDate,
'levelTest' => $levelTestInfo,
'isDiscount' => $isDiscount,
'discountAmount' => $discountAmount,
'discountType' => $discountType,
'parameter' => $parameter,
]);
}
//Acheter
/**
* @Route("/order/purchase/{id}", name="session_purchase", requirements={"id":"\d+"}), methods={"GET","POST"})
* @ParamConverter("session", options={"id" : "id"})
* @Security("is_granted('ROLE_USER')")
* @param Session $session
* @param Request $request
* @param OrderHelper $orderHelper
* @param SessionSymfo $sessionSymfo
* @param StripePlanForGroupRepository $stripePlanForGroupRepository
*
* @return Response
*/
public function purchase(Session $session, Request $request, OrderHelper $orderHelper, SessionSymfo $sessionSymfo, StripePlanForGroupRepository $stripePlanForGroupRepository,
DiscountRepository $discountRepository, CurrencyChangeService $currencyChangeService
): Response {
$isDiscount = false;
$sessionPrice = $session->getPrice();
$parameter = $request->query->get('d');
$discount = $discountRepository->findOneBy([
'urlParameter' => $parameter,
]);
if ($discount) {
/** @var StripePlanForGroup $plan */
$plan = $stripePlanForGroupRepository->findOneBy([
'subject' => $session->getLevel()->getSubject(),
'isDiscount' => true,
'discount' => $discount,
]);
if ($plan) {
$isDiscount = true;
$discountAmount = $discount->getAmount();
$discountType = $discount->getType();
if ($discountType == 'fixe') {
$sessionPrice = $sessionPrice - $discountAmount;
} else {
$deduction = ($sessionPrice - $discountAmount) / 100;
$sessionPrice = $sessionPrice - $deduction;
}
} else {
/** @var StripePlanForGroup $plan */
$plan = $stripePlanForGroupRepository->findOneBy([
'subject' => $session->getLevel()->getSubject(),
'isDiscount' => false,
]);
}
} else {
/** @var StripePlanForGroup $plan */
$plan = $stripePlanForGroupRepository->findOneBy([
'subject' => $session->getLevel()->getSubject(),
'isDiscount' => false,
]);
}
$planId = $plan->getStripeId();
$user = $this->getUser();
$gender = $session->getTeacher()->getUserId()->getGender();
if ($sessionSymfo->get('code-group')) {
$stripeCoupon = $sessionSymfo->get('code-group');
$code = $stripeCoupon->amount_off / 100;
} else {
$stripeCoupon = false;
$code = 0;
}
$currency = $currencyChangeService->getCurrencyChangeForView($request);
$sessionPrice = round($sessionPrice * $currency['currencyRate']);
$error = false;
if ($request->isMethod('POST')) {
$token = $request->request->get('stripeToken');
$participant = $request->request->get('child-select');
$paymentType = $request->request->get('paymentType');
if ($session->getSeat() > 0) {
try {
if ($paymentType == "twoTime") {
//paiement en deux fois
$invoice = $orderHelper->chargeCustomerForInstallement($token, $user, $planId);
} else {
if ($session->getPrice() == 0) {
$sessionOrder = $this->addSessionOrderToBdd($session, $user, "gratuit", 0, null, null, null, null, false, $participant);
$this->addFlash('success', 'Inscription completée ! Un mail vous a été envoyé, vérifiez vos courriers indésirables (SPAM) si vous ne l\'avez pas reçu.');
return $this->redirectToRoute(
'confirmation_purchase',
[
'userId' => $user->getId(),
'orderType' => 'group',
'orderId' => $sessionOrder->getId(),
'_locale' => $request->getLocale(),
]
);
} else {
$invoice = $orderHelper->chargeCustomerSession($token, $user, $session, $stripeCoupon, $sessionPrice);
}
}
} catch (\Stripe\Exception\CardException $e) {
//error_log("A payment error occurred: {$e->getError()->message}");
$error = 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
} catch (\Stripe\Exception\InvalidRequestException $e) {
$error = 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
} catch (\Exception $e) {
//error_log("Another problem occurred, maybe unrelated to Stripe.");
$error = 'Il y a un problème pour charger votre carte: '.$e;
}
if ( ! $error and $invoice->paid == true) {
$sessionOrder = $this->prepareCreationSessionOrderWithInvoice($invoice, $user, $session, $participant, $paymentType);
$this->addFlash('success', 'Inscription completée ! Un mail vous a été envoyé, vérifiez vos courriers indésirables (SPAM) si vous ne l\'avez pas reçu.');
$this->activeCampaignHelper->addOrder($sessionOrder);
$this->activeCampaignHelper->updateCustomFieldLastLevelTestForContact($sessionOrder->getStudents()->getEmail(), $session);
return $this->redirectToRoute(
'confirmation_purchase',
[
'userId' => $user->getId(),
'orderType' => 'group',
'orderId' => $sessionOrder->getId(),
'_locale' => $request->getLocale(),
]
);
} else {
$this->addFlash('error', $error);
return $this->redirectToRoute('session_purchase', [
'id' => $session->getId(),
'_locale' => $request->getLocale(),
]);
}
} else {
$this->addFlash('error', "Le groupe est complet, merci d'en choisir un autre");
return $this->redirectToRoute('session_index', [
'gender' => $gender,
'_locale' => $request->getLocale(),
]);
}
}
return $this->render('session/purchase.html.twig', [
'stripe_public_key' => $this->getParameter('stripe_public_key'),
'session' => $session,
'currentUser' => $user,
'errorCard' => $error,
'code' => $code,
'plan' => $plan,
'price' => $sessionPrice,
'isDiscount' => $isDiscount,
'currency' => $currency,
]);
}
/**
* @Route("/order/success/takallam", name="session_success_takallam", methods={"GET","POST"})
*/
public function successTakallam(Request $request)
{
dd($request);
return $this->render('session/registration-takallam-success.twig');
}
/**
* @Route("/coupon", name="session_coupon_add", methods={"POST"})
* @Security("is_granted('ROLE_USER')")
* @param Request $request
* @param StripeClient $stripeClient
* @param SessionSymfo $sessionSymfo
*
* @return RedirectResponse
*/
public function addCouponAction(Request $request, StripeClient $stripeClient, SessionSymfo $sessionSymfo): RedirectResponse
{
$referer = $request->headers->get('referer');
$code = $request->request->get('code');
if ( ! $code) {
$this->addFlash('error', 'Vous n\'avez entré aucun coupon');
return $this->redirect($referer);
}
try {
$stripeCoupon = $stripeClient->findCoupon($code);
} catch (\Stripe\Exception\InvalidRequestException $e) {
$this->addFlash('error', 'Coupon Invalide');
return $this->redirect($referer);
}
if ($stripeCoupon->percent_off != null) {
$this->addFlash('error', 'Coupon invalide pour ces cours');
return $this->redirect($referer);
}
if ( ! $stripeCoupon->valid) {
$this->addFlash('error', 'Coupon expiré');
return $this->redirect($referer);
}
$sessionSymfo->set('code-group', $stripeCoupon);
return $this->redirect($referer);
}
/**
* @param Invoice $invoice
* @param User $user
* @param Session $session
* @param $participant
* @param $paymentType
*/
private function prepareCreationSessionOrderWithInvoice(Invoice $invoice, User $user, Session $session, $participant, $paymentType)
{
$stripeCustomerId = $invoice->customer;
$stripeCustomer = \Stripe\Customer::retrieve($stripeCustomerId);
if ($paymentType == "twoTime") {
$stripeSubscriptionId = $invoice->subscription;
$stripeSubscription = \Stripe\Subscription::retrieve($stripeSubscriptionId);
$subscriptionStatus = $stripeSubscription->status;
if ($subscriptionStatus == 'active') {
$paidAmount = ($invoice->amount_paid / 100) * 2;
$nextPaymentTimeStamp = $stripeSubscription->current_period_end;
} else {
$this->addFlash('error', "Votre paiement n'a pas abouti");
return $this->redirectToRoute('session_purchase', [
'id' => $session->getId(),
'_locale' => $user->getLanguage()->getPole(),
]);
}
} else {
$paidAmount = $invoice->amount_paid / 100;
$stripeSubscription = null;
$nextPaymentTimeStamp = null;
$stripeSubscriptionId = null;
}
$cardDetails = $this->stripeClient->retrieveSource($stripeCustomerId, $stripeCustomer->default_source);
$isTwoTime = $paymentType == "twoTime";
$cardBrand = $cardDetails->brand;
$cardLastDigits = $cardDetails->last4;
$order = $this->addSessionOrderToBdd(
$session,
$user,
$stripeCustomerId,
$paidAmount,
$cardBrand,
$cardLastDigits,
$nextPaymentTimeStamp,
$stripeSubscriptionId,
$isTwoTime,
$participant
);
return $order;
}
private function addSessionOrderToBdd(Session $session, User $user, $stripeCustomerId, $paidAmount, $cardBrand, $cardLastDigit, $nextPaymentTimeStamp, $stripeSubscriptionId,
bool $isTwoTime, $participant
) {
$childRepo = $this->em->getRepository(Child::class);
if ($participant) {
$participant = $childRepo->findOneBy(['id' => $participant]);
} else {
$participant = null;
}
$order = new SessionOrder();
$order->setSession($session)
->setStripeCustomerId($stripeCustomerId)
->setAmountPaid($paidAmount)
->setIsActif(true)
->setCanceledByStudent(false)
->setCanceledByUs(false)
->setCardBrand($cardBrand)
->setCardLast4($cardLastDigit)
->setIsTwoTime($isTwoTime)
->setNextPaymentTimeStamp($nextPaymentTimeStamp)
->setStripeSubscriptionId($stripeSubscriptionId)
->setParticipant($participant)
->setStudents($user)
->setPaymentNb(1);
$session->decrementSeat();
$this->em->persist($session);
$this->em->persist($order);
$this->em->flush();
$program = $order->getSession()->getLevel()->getProgramUrls();
$this->emailNotification->notifyStudentSessionOrder($order, $user, $program);
//$this->slackClient->notifySecretariatGroupSessionInscription($order, $user);
return $order;
}
}