src/Controller/Subscription/UserSubscriptionController.php line 416

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Subscription;
  3. use App\Entity\Category;
  4. use App\Entity\Discount;
  5. use App\Entity\SubjectLevel;
  6. use App\Entity\SubscriptionOrder;
  7. use App\Entity\Teacher;
  8. use App\Entity\User;
  9. use App\Form\SubscriptionPrivateOrderType;
  10. use App\Helper\BookHelper;
  11. use App\Helper\CourseHelper;
  12. use App\Helper\SubscriptionHelper;
  13. use App\Notification\EmailNotification;
  14. use App\Notification\SlackClient;
  15. use App\Repository\DiscountRepository;
  16. use App\Repository\HolidayRepository;
  17. use App\Repository\PaidCourseListRepository;
  18. use App\Repository\PlanRepository;
  19. use App\Repository\SubjectLevelRepository;
  20. use App\Repository\SubjectRepository;
  21. use App\Repository\SubscriptionOrderRepository;
  22. use App\Repository\TeacherScheduleRepository;
  23. use App\Service\Currency\CurrencyChangeService;
  24. use App\Service\Localisation\CountryInfoService;
  25. use App\Service\Localisation\GeoIPService;
  26. use App\StripeClient;
  27. use DateTimeImmutable;
  28. use Doctrine\ORM\EntityManagerInterface;
  29. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  30. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  31. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  32. use Symfony\Component\HttpFoundation\RedirectResponse;
  33. use Symfony\Component\HttpFoundation\Request;
  34. use Symfony\Component\HttpFoundation\Response;
  35. use Symfony\Component\HttpFoundation\Session\Session;
  36. use Symfony\Component\Routing\Annotation\Route;
  37. use Symfony\Polyfill\Intl\Icu\Currencies;
  38. use Symfony\Polyfill\Intl\Icu\NumberFormatter;
  39. /**
  40.  * @Route("user/subscription")
  41.  * @Security("is_granted('ROLE_USER')")
  42.  */
  43. class UserSubscriptionController extends AbstractController
  44. {
  45.     private $subscriptionHelper;
  46.     private $bookHelper;
  47.     //Acheter OK
  48.     //Voir
  49.     //Editer
  50.     //Renouveler OK
  51.     //Reactiver
  52.     //Supprimer
  53.     public function __construct(SubscriptionHelper $subscriptionHelperBookHelper $bookHelper)
  54.     {
  55.         $this->subscriptionHelper $subscriptionHelper;
  56.         $this->bookHelper         $bookHelper;
  57.     }
  58.     /**
  59.      * @Route("/{category}/{teacher}/checkout", name="subscription_checkout")
  60.      * @ParamConverter("category", options={"mapping": {"category" : "name"}})
  61.      * @ParamConverter("teacher", options={"mapping": {"teacher" : "id"}})
  62.      */
  63.     public function orderSubscription(Request                $requestCategory $categoryTeacher $teacherSubscriptionOrderRepository $subscriptionOrderRepository,
  64.                                       SubjectRepository      $subjectRepositoryDiscountRepository $discountRepositoryStripeClient $stripeClient,
  65.                                       SubjectLevelRepository $subjectLevelRepositoryCurrencyChangeService $currencyChangeService
  66.     ) {
  67.         /** @var User $user */
  68.         $user $this->getUser();
  69.         $parameter $request->query->get('d');
  70.         /** @var Discount $discount */
  71.         $discount $discountRepository->findOneBy([
  72.                                                        'urlParameter' => $parameter,
  73.                                                        'isForGroup'   => false,
  74.                                                    ]);
  75.         if ($discount) {
  76.             $couponStripeName $discount->getStripeName();
  77.             $discountType     $discount->getType();
  78.             try {
  79.                 $stripeCoupon $stripeClient->findCoupon($couponStripeName);
  80.                 if ($stripeCoupon->valid) {
  81.                     $isDiscount true;
  82.                     $request->getSession()->set('code-subscription'$stripeCoupon);
  83.                 } else {
  84.                     $isDiscount     false;
  85.                     $discountAmount 0;
  86.                     $discountType   null;
  87.                     $stripeCoupon   false;
  88.                     $this->addFlash(
  89.                         'error',
  90.                         ' Coupon invalid'
  91.                     );
  92.                 }
  93.             } catch (\Stripe\Exception\InvalidRequestException $e) {
  94.                 $isDiscount     false;
  95.                 $discountAmount 0;
  96.                 $discountType   null;
  97.                 $stripeCoupon   false;
  98.                 $this->addFlash(
  99.                     'error',
  100.                     $e.' Coupon invalid'
  101.                 );
  102.             }
  103.         } else {
  104.             $stripeCoupon   false;
  105.             $isDiscount     false;
  106.             $discountAmount 0;
  107.             $discountType   null;
  108.         }
  109.         //reception possible : beginner, intermediate, advanced
  110.         $autoAssignLevel $request->query->get('level');
  111.         if ($autoAssignLevel !== "intermediate" && $autoAssignLevel !== "advanced" && $autoAssignLevel !== "beginner") {
  112.             $autoAssignLevel null;
  113.         }
  114.         //reception possible: "0", "1"
  115.         $isChild $request->query->get('child');
  116.         if ($isChild != "0" && $isChild != "1") {
  117.             $isChild null;
  118.         }
  119.         $categoryEn $category->getNameEn();
  120.         $error false;
  121.         $currency $currencyChangeService->getCurrencyChangeForView($request);
  122.         //$stripeCoupon = $request->getSession()->get('code-subscription', false);
  123.         $subscriptionOrder = new SubscriptionOrder();
  124.         $subscriptionOrder->setTeacher($teacher);
  125.         $subscriptionOrder->setCategory($category);
  126.         $subscriptionOrder->setUser($user);
  127.         $form $this->createForm(SubscriptionPrivateOrderType::class, $subscriptionOrder, [
  128.             'locale'  => $request->getLocale(),
  129.             'isChild' => $isChild,
  130.         ]);
  131.         $form->handleRequest($request);
  132.         if ($form->isSubmitted() && $form->isValid()) {
  133.             $request->getSession()->remove('code-subscription');
  134.             /** @var SubscriptionOrder $subscriptionOrder */
  135.             $subscriptionOrder $form->getData();
  136.             //Reception data possible : all, chafawi, naho, qiraa, sarf, balagha,child-program, quran,tajwid, quran-child
  137.             $requestedProgram $request->get('subscription_private_order') ? $request->get('subscription_private_order')['program'] : null;
  138.             $subscriptionOrder->setPurchaseDate(new \DateTimeImmutable())
  139.                               ->setTotalLostMinutes(0)
  140.                               ->setRamadanCreditAmount(0);
  141.             foreach ($subscriptionOrder->getSchedules() as $teacherSchedule) {
  142.                 $repeatedSubscription $subscriptionOrderRepository->findRepeatedOrder($teacherSchedule);
  143.                 if ($repeatedSubscription) {
  144.                     $this->addFlash(
  145.                         'error',
  146.                         "Ce Planning vient d'être réservé, si vous venez de le reserver, il se peut que cette erreur vienne du fait que vous ayez cliquez plusieurs fois sur le bouton s'inscrire"
  147.                     );
  148.                     return $this->redirectToRoute(
  149.                         'schedule_list',
  150.                         [
  151.                             'category' => $category,
  152.                             'gender'   => $user->getGender()->getName(),
  153.                             '_locale'  => $request->getLocale(),
  154.                         ]
  155.                     );
  156.                 }
  157.             }
  158.             $plan $subscriptionOrder->getPlan();
  159.             if ($stripeCoupon) {
  160.                 if ($plan->getFrequency() != $discount->getPlan()) {
  161.                     $stripeCoupon false;
  162.                 }
  163.             }
  164.             $token       $request->get('stripeToken');
  165.             $quantity    $subscriptionOrder->getNbOfScheduleChoose();
  166.             $participant $subscriptionOrder->getParticipant();
  167.             $schedules   $subscriptionOrder->getSchedules();
  168.             try {
  169.                 $stripeSubscription $this->subscriptionHelper->chargeCustomer($token$user$plan$quantity$stripeCoupon$schedules);
  170.             } catch (\Stripe\Exception\CardException $e) {
  171.                 //error_log("A payment error occurred: {$e->getError()->message}");
  172.                 $error 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
  173.             } catch (\Stripe\Exception\InvalidRequestException $e) {
  174.                 $error 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
  175.             } catch (\Exception $e) {
  176.                 //error_log("Another problem occurred, maybe unrelated to Stripe.");
  177.                 $error 'Il y a un problème pour charger votre carte: '.$e;
  178.             }
  179.             /*catch (\Stripe\Error\Card $e) {
  180.                 $error = 'Il y a un problème pour charger votre carte: '.$e->getMessage();
  181.             }
  182.             */
  183.             if ( ! $error) {
  184.                 if ($stripeSubscription->status == 'active') {
  185.                     $this->addFlash(
  186.                         'success',
  187.                         'Votre inscription a été reçue. Elle sera validée lorsque le paiement sera confirmé. Vous recevrez un email et vos cours seront visibles dans votre espace membre'
  188.                     );
  189.                     // $requestedProgram à lier avec les entités Subject dans la BDD avec le tag
  190.                     //all -> alKunuz
  191.                     //chafawi -> oral
  192.                     //naho -> ajromiyah
  193.                     //qiraa -> texteMedine
  194.                     //sarf -> sarf-private
  195.                     //balagha -> balagha
  196.                     //child-program -> tresorsEnfant
  197.                     //quran -> coranComplet
  198.                     //tajwid -> tajweed
  199.                     //quran-child -> coranCompletChildren
  200.                     //nouraniyah -> an Nouraniyah
  201.                     $level null;
  202.                     if ($requestedProgram == "all") {
  203.                         $subject $subjectRepository->findOneBy(['tagName' => "alKaamil"]);
  204.                     } elseif ($requestedProgram == "chafawi") {
  205.                         $subject $subjectRepository->findOneBy(['tagName' => "oralExpression"]);
  206.                     } elseif ($requestedProgram == "naho") {
  207.                         $subject $subjectRepository->findOneBy(['tagName' => "ajromiyah"]);
  208.                         /** @var SubjectLevel $level */
  209.                         $level $subjectLevelRepository->findOneBy([
  210.                                                                         'subject' => $subject,
  211.                                                                         'level'   => 1,
  212.                                                                     ]);
  213.                     } elseif ($requestedProgram == "qiraa") {
  214.                         $subject $subjectRepository->findOneBy(['tagName' => "medinaTexte"]);
  215.                         /** @var SubjectLevel $level */
  216.                         $level $subjectLevelRepository->findOneBy([
  217.                                                                         'subject' => $subject,
  218.                                                                         'level'   => 1,
  219.                                                                     ]);
  220.                     } elseif ($requestedProgram == "sarf") {
  221.                         //pas de niveau
  222.                         $subject $subjectRepository->findOneBy(['tagName' => "sarf"]);
  223.                     } elseif ($requestedProgram == "balagha") {
  224.                         //pas de niveau
  225.                         $subject $subjectRepository->findOneBy(['tagName' => "balagha"]);
  226.                     } elseif ($requestedProgram == "child-program") {
  227.                         // a des niveaux mais dois passser un test
  228.                         $subject $subjectRepository->findOneBy(['tagName' => "tresorEnfant"]);
  229.                     } elseif ($requestedProgram == "quran") {
  230.                         $subject $subjectRepository->findOneBy(['tagName' => "coranComplet"]);
  231.                     } elseif ($requestedProgram == "tajwid") {
  232.                         $subject $subjectRepository->findOneBy(['tagName' => "tajweedBeginner"]);
  233.                     } elseif ($requestedProgram == "quran-child") {
  234.                         $subject $subjectRepository->findOneBy(['tagName' => "coranCompletChildren"]);;
  235.                     } elseif ($requestedProgram == "nouraniyah") {
  236.                         $subject $subjectRepository->findOneBy(['tagName' => "nouraniyah"]);
  237.                     } else {
  238.                         if ($subscriptionOrder->getCategory()->getNameEn() == 'Arabic') {
  239.                             if ($isChild) {
  240.                                 $subject $subjectRepository->findOneBy(['tagName' => "tresorEnfant"]);
  241.                             } else {
  242.                                 $subject $subjectRepository->findOneBy(['tagName' => "alKaamil"]);
  243.                             }
  244.                         } else {
  245.                             if ($isChild) {
  246.                                 $subject $subjectRepository->findOneBy(['tagName' => "coranCompletChildren"]);
  247.                             } else {
  248.                                 $subject $subjectRepository->findOneBy(['tagName' => "coranComplet"]);
  249.                             }
  250.                         }
  251.                     }
  252.                     if ($requestedProgram == null) {
  253.                         if ($subscriptionOrder->getCategory()->getNameEn() == 'Arabic') {
  254.                             if ($isChild) {
  255.                                 $subject $subjectRepository->findOneBy(['tagName' => "tresorEnfant"]);
  256.                             } else {
  257.                                 $subject $subjectRepository->findOneBy(['tagName' => "alKaamil"]);
  258.                             }
  259.                         } else {
  260.                             if ($isChild) {
  261.                                 $subject $subjectRepository->findOneBy(['tagName' => "coranCompletChildren"]);
  262.                             } else {
  263.                                 $subject $subjectRepository->findOneBy(['tagName' => "coranComplet"]);
  264.                             }
  265.                         }
  266.                     }
  267.                     //TODO utiliser Messenger
  268.                     $subscriptionOrder $this->subscriptionHelper->addSubscriptionInBDD(
  269.                         $subscriptionOrder->getUser(),
  270.                         $plan,
  271.                         $schedules,
  272.                         $category,
  273.                         $teacher,
  274.                         $quantity,
  275.                         $stripeSubscription,
  276.                         $subject,
  277.                         $level,
  278.                         $participant
  279.                     );
  280.                     //TODO utiliser Messenger
  281.                     $this->subscriptionHelper->sendNotificationForNewSubscription($subscriptionOrder);
  282.                     if ( ! $subject) {
  283.                         //TODO utiliser Messenger
  284.                         $this->subscriptionHelper->sendAlertNoSubject($subscriptionOrder);
  285.                     }
  286.                     //TODO utiliser Messenger
  287.                     if ($requestedProgram != "quran" and $requestedProgram != "quran-child") {
  288.                         $this->bookHelper->getChoosenBookForSubscription($subject$subscriptionOrder$level);
  289.                     }
  290.                     return $this->redirectToRoute(
  291.                         'confirmation_purchase',
  292.                         [
  293.                             'userId'    => $user->getId(),
  294.                             'orderType' => 'subscription',
  295.                             'orderId'   => $subscriptionOrder->getId(),
  296.                             '_locale'   => $request->getLocale(),
  297.                         ]
  298.                     );
  299.                 } else {
  300.                     $this->addFlash('error'"Votre Paiement n'a pas été accepté par votre banque");
  301.                     return $this->redirectToRoute(
  302.                         'subscription_checkout',
  303.                         [
  304.                             'category' => $category->getName(),
  305.                             'teacher'  => $teacher->getId(),
  306.                             '_locale'  => $request->getLocale(),
  307.                         ]
  308.                     );
  309.                 }
  310.             } else {
  311.                 $this->addFlash('error'$error);
  312.                 return $this->redirectToRoute(
  313.                     'subscription_checkout',
  314.                     [
  315.                         'category' => $category->getName(),
  316.                         'teacher'  => $teacher->getId(),
  317.                         '_locale'  => $request->getLocale(),
  318.                     ]
  319.                 );
  320.             }
  321.         }
  322.         return $this->render(
  323.             'schedule/purchase.html.twig',
  324.             [
  325.                 'form'              => $form->createView(),
  326.                 'categoryName'      => $category,
  327.                 'teacher'           => $teacher,
  328.                 'user'              => $user,
  329.                 'stripe_public_key' => $this->getParameter('stripe_public_key'),
  330.                 'local'             => $this->getParameter('locale'),
  331.                 'errorCard'         => $error,
  332.                 'categoryEn'        => $categoryEn,
  333.                 'code'              => ($stripeCoupon !== false) ? $stripeCoupon->percent_off 0,
  334.                 'isChild'           => $isChild,
  335.                 'discount'          => $discount,
  336.                 'isDiscount'        => $isDiscount,
  337.                 'currency'          => $currency,
  338.             ]
  339.         );
  340.     }
  341.     /**
  342.      * @Route("/{id}/resubscribe", name="subscription_resubscribe")
  343.      * @param SubscriptionOrder $oldSubscriptionOrder
  344.      * @param PlanRepository $planRepository
  345.      * @param Request $request
  346.      * @param Session $sessionSymfo
  347.      *
  348.      * @return RedirectResponse|Response
  349.      */
  350.     public function reSubscribe(SubscriptionOrder $oldSubscriptionOrderPlanRepository $planRepositoryRequest $requestSession $sessionSymfoCurrencyChangeService $currencyChangeService
  351.     ) {
  352.         /** @var User $user */
  353.         $user $oldSubscriptionOrder->getUser();
  354.         //Montrer les nouveaux plan qui ne sont pas de la même fréquence. Au cas où l'élève souhaite changer de rythme (il passe au nouveau tarif, je ne montre donc pas les anciens plans)
  355.         $activePlan $planRepository->getPlanToEditFrequencyFromOldToNew($oldSubscriptionOrder->getCategory(), $oldSubscriptionOrder->getPlan()->getFrequency());
  356.         $error false;
  357.         if ($sessionSymfo->get('code-subscription')) {
  358.             $stripeCoupon $sessionSymfo->get('code-subscription');
  359.             $code         $stripeCoupon->percent_off;
  360.         } else {
  361.             $stripeCoupon false;
  362.             $code         0;
  363.         }
  364.         $currency $currencyChangeService->getCurrencyChangeForView($request);
  365.         if ($request->isMethod('POST')) {
  366.             $token        $request->request->get('stripeToken');
  367.             $quantity     $request->get('quantity');
  368.             $planStripeId $request->get('frequency');
  369.             $schedules    $request->get('schedule');
  370.             $participant  $oldSubscriptionOrder->getParticipant();
  371.             if ( ! $quantity) {
  372.                 $this->addFlash('error''Ne PAS taper sur la touche entrer de votre clavier pour envoyer le formulaire, mais CLIQUEZ sur le boutton "S\'inscrire" avec votre souris ');
  373.                 return $this->redirectToRoute(
  374.                     'subscription_resubscribe',
  375.                     [
  376.                         'id'      => $oldSubscriptionOrder->getId(),
  377.                         '_locale' => $request->getLocale(),
  378.                     ]
  379.                 );
  380.             }
  381.             if ($planStripeId == null) {
  382.                 $this->addFlash('error'"Merci de choisir un rythme d'abonnement");
  383.                 return $this->redirectToRoute(
  384.                     'subscription_resubscribe',
  385.                     [
  386.                         'id'      => $oldSubscriptionOrder->getId(),
  387.                         '_locale' => $request->getLocale(),
  388.                     ]
  389.                 );
  390.             }
  391.             $plan $planRepository->findOneBy(
  392.                 [
  393.                     'stripeId' => $planStripeId,
  394.                 ]
  395.             );
  396.             if ($stripeCoupon != false) {
  397.                 if ($plan->getFrequency() != "mensuel") {
  398.                     $stripeCoupon false;
  399.                 }
  400.             }
  401.             $subject $oldSubscriptionOrder->getSubject();
  402.             $level   $oldSubscriptionOrder->getSubjectLevel();
  403.             try {
  404.                 $stripeSubscription $this->subscriptionHelper->chargeCustomer($token$user$plan$quantity$stripeCoupon$schedules);
  405.             } catch (\Stripe\Exception\CardException $e) {
  406.                 //error_log("A payment error occurred: {$e->getError()->message}");
  407.                 $error 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
  408.             } catch (\Stripe\Exception\InvalidRequestException $e) {
  409.                 $error 'Il y a un problème pour charger votre carte: '.$e->getError()->message;
  410.             } catch (\Exception $e) {
  411.                 //error_log("Another problem occurred, maybe unrelated to Stripe.");
  412.                 $error 'Il y a un problème pour charger votre carte: '.$e;
  413.             }
  414.             if ( ! $error) {
  415.                 if ($stripeSubscription->status == 'active') {
  416.                     $this->addFlash(
  417.                         'success',
  418.                         'Votre inscription a été reçue. Elle sera validée lorsque le paiement sera confirmé. Vous recevrez un email et vos cours seront visibles dans votre espace membre'
  419.                     );
  420.                     //TODO utiliser Messenger
  421.                     $newSubscriptionOrder $this->subscriptionHelper->addSubscriptionInBDD(
  422.                         $user,
  423.                         $plan,
  424.                         $schedules,
  425.                         $oldSubscriptionOrder->getCategory(),
  426.                         $oldSubscriptionOrder->getTeacher(),
  427.                         $quantity,
  428.                         $stripeSubscription,
  429.                         $subject,
  430.                         $level,
  431.                         $participant,
  432.                         $oldSubscriptionOrder
  433.                     );
  434.                     //TODO utiliser Messenger
  435.                     $this->subscriptionHelper->sendNotificationForNewSubscription($newSubscriptionOrder);
  436.                     return $this->redirectToRoute(
  437.                         'user_courses',
  438.                         [
  439.                             'order'   => $oldSubscriptionOrder->getCategory()->getName(),
  440.                             '_locale' => $request->getLocale(),
  441.                         ]
  442.                     );
  443.                 } else {
  444.                     $this->addFlash('error'"Votre Paiement n'a pas été accepté par votre banque");
  445.                     return $this->redirectToRoute(
  446.                         'subscription_resubscribe',
  447.                         [
  448.                             'id'      => $oldSubscriptionOrder->getId(),
  449.                             '_locale' => $request->getLocale(),
  450.                         ]
  451.                     );
  452.                 }
  453.             } else {
  454.                 $this->addFlash('error'$error);
  455.                 return $this->redirectToRoute(
  456.                     'subscription_resubscribe',
  457.                     [
  458.                         'id'      => $oldSubscriptionOrder->getId(),
  459.                         '_locale' => $request->getLocale(),
  460.                     ]
  461.                 );
  462.             }
  463.         }
  464.         return $this->render(
  465.             'profil/resuscribe.html.twig',
  466.             [
  467.                 'user'              => $user,
  468.                 'subscription'      => $oldSubscriptionOrder,
  469.                 'schedules'         => $oldSubscriptionOrder->getSchedules(),
  470.                 'errorCard'         => $error,
  471.                 'stripe_public_key' => $this->getParameter('stripe_public_key'),
  472.                 'code'              => $code,
  473.                 'plans'             => $activePlan,
  474.                 'currency'          => $currency,
  475.             ]
  476.         );
  477.     }
  478.     /**
  479.      * @Route("/checkout/coupon", name="subscription_checkout_coupon_add", methods={"POST"})
  480.      */
  481.     public function addCouponAction(Request $requestStripeClient $stripeClient): Response
  482.     {
  483.         $code $request->request->get('code');
  484.         if ( ! $code) {
  485.             return $this->json(['success' => 0'message' => 'Vous n\'avez entré aucun coupon']);
  486.         }
  487.         try {
  488.             $stripeCoupon $stripeClient->findCoupon($code);
  489.         } catch (\Stripe\Error\InvalidRequest $e) {
  490.             return $this->json(['success' => 0'message' => 'Coupon Invalide']);
  491.         }
  492.         if ($stripeCoupon->amount_off != null) {
  493.             return $this->json(['success' => 0'message' => 'Coupon invalide pour ces cours']);
  494.         }
  495.         if ( ! $stripeCoupon->valid) {
  496.             return $this->json(['success' => 0'message' => 'Coupon expiré']);
  497.         }
  498.         $request->getSession()->set('code-subscription'$stripeCoupon);
  499.         return $this->json(['success' => 1'message' => 'Le coupon a été ajouté''amount' => $stripeCoupon->percent_off]);
  500.     }
  501.     //TODO refacto pour code dupliquer à retravailler
  502.     /**
  503.      * @Route("/{id}/{teacher}/changeteacher", name="subscription_change_teacher")
  504.      * @param SubscriptionOrder $subscriptionOrder
  505.      * @param Teacher $teacher
  506.      * @param TeacherScheduleRepository $teacherScheduleRepository
  507.      * @param Request $request
  508.      * @param PaidCourseListRepository $paidCourseListRepository
  509.      * @param EntityManagerInterface $em
  510.      * @param EmailNotification $emailNotification
  511.      * @param SlackClient $slackClient
  512.      * @param HolidayRepository $holidayRepository
  513.      * @param SubscriptionHelper $subscriptionHelper
  514.      * @param CourseHelper $courseHelper
  515.      *
  516.      * @return RedirectResponse|Response
  517.      */
  518.     public function modifySubscriptionSchedulesAndTeacher(SubscriptionOrder        $subscriptionOrderTeacher $teacherTeacherScheduleRepository $teacherScheduleRepository,
  519.                                                           Request                  $request,
  520.                                                           PaidCourseListRepository $paidCourseListRepositoryEntityManagerInterface $emEmailNotification $emailNotification,
  521.                                                           SlackClient              $slackClientHolidayRepository $holidayRepositorySubscriptionHelper $subscriptionHelper,
  522.                                                           CourseHelper             $courseHelper
  523.     ) {
  524.         $freeSchedules $teacherScheduleRepository->findForStudentFreeSchedulesForOneTeacher($teacher);
  525.         $oldTeacher $subscriptionOrder->getTeacher();
  526.         if ( ! $this->isGranted('ROLE_SUPPORT')) {
  527.             if ($subscriptionHelper->hasCourseToday($subscriptionOrder)) {
  528.                 $this->addFlash('error'"Vous avez cours aujourd'hui, vous ne pouvez donc pas changer de planning. Merci de modifier votre planning un jour où vous n'avez pas cours");
  529.                 return $this->redirectToRoute(
  530.                     'user_subscription_show',
  531.                     [
  532.                         'id'      => $subscriptionOrder->getId(),
  533.                         '_locale' => $request->getLocale(),
  534.                     ]
  535.                 );
  536.             }
  537.         }
  538.         if ($request->isMethod('POST')) {
  539.             $holidays $holidayRepository->findAll();
  540.             //Je compte le nb de cours annulé pour les vacances avant le changement de planning
  541.             $arrayCanceledCourseForHoliday $paidCourseListRepository->findNumberCanceledCourseForHolidayAfterScheduleChangeWithQuery($subscriptionOrder)->getQuery()->getArrayResult();;
  542.             $nbCanceledCoursesForHoliday sizeof($arrayCanceledCourseForHoliday);
  543.             $schedules $request->get('newSchedule');
  544.             foreach ($schedules as $oldScheduleId => $newScheduleId) {
  545.                 if ($newScheduleId) {
  546.                     $oldSchedule $teacherScheduleRepository->findOneBy(['id' => $oldScheduleId]);
  547.                     $remainCourses $paidCourseListRepository->findAllRemainCourseAfterScheduleChange($subscriptionOrder$oldSchedule);
  548.                     if ($remainCourses == null) {
  549.                         $this->addFlash(
  550.                             'error',
  551.                             'Il ne vous reste plus de nouveaux cours à prendre pour pouvoir changer de professeur. Une fois vos nouveaux cours ajoutés (quand une nouvelle mensualité sera débitée) vous pourrez revenir sur cette page et changer de professeur.'
  552.                         );
  553.                         return $this->redirectToRoute(
  554.                             'user_subscription_show',
  555.                             [
  556.                                 'id'      => $subscriptionOrder->getId(),
  557.                                 '_locale' => $request->getLocale(),
  558.                             ]
  559.                         );
  560.                     }
  561.                 } else {
  562.                     $this->addFlash('error''Merci de choisir un nouveau planning pour remplacer TOUS vos anciens plannings');
  563.                     return $this->redirectToRoute(
  564.                         'subscription_change_teacher',
  565.                         [
  566.                             'id'      => $subscriptionOrder->getId(),
  567.                             'teacher' => $teacher->getId(),
  568.                             '_locale' => $request->getLocale(),
  569.                         ]
  570.                     );
  571.                 }
  572.             }
  573.             foreach ($schedules as $oldScheduleId => $newScheduleId) {
  574.                 if ($newScheduleId) {
  575.                     $oldSchedule $teacherScheduleRepository->findOneBy(['id' => $oldScheduleId]);
  576.                     $newSchedule $teacherScheduleRepository->findOneBy(['id' => $newScheduleId]);
  577.                     //Récupérer tout les cours qui ne seront pas fait :
  578.                     $remainCourses $paidCourseListRepository->findAllRemainCourseAfterScheduleChange($subscriptionOrder$oldSchedule);
  579.                     //permettre le changement de planning uniquement s'il reste des cours à prendre
  580.                     if ($remainCourses != null) {
  581.                         //Récupérer le prochain cours qui aurait du avoir lieu pour en faire la date de libération du oldPlanning (freeDate)
  582.                         $nextCourse $paidCourseListRepository->findNextCourseAfterScheduleChange($oldSchedule);
  583.                         $nextCourseDate DateTimeImmutable::createFromMutable($nextCourse->getCourseDate());
  584.                         //Je récupère la date de paiement de ce cours pour le réutiliser pour la nouveau planning, certain abo n'ont pas de paiement date car ce sont des ajout manuel, donc je code en défensive
  585.                         if ($nextCourse->getPaymentDate() != null) {
  586.                             $paymentDate $nextCourse->getPaymentDate();
  587.                         } else {
  588.                             $paymentDate null;
  589.                         }
  590.                         //Je récupère le montant du cours pour le réutiliser pour les nouveaux cours de la liste
  591.                         $priceCourse $nextCourse->getPrice();
  592.                         //Libérer l'ancien planning immédiatement
  593.                         $oldSchedule->setFreeDate($nextCourseDate)
  594.                                     ->setIsFree(true)
  595.                                     ->setSubscriptionOrder(null)
  596.                                     ->setOccupiedUntil(null);
  597.                         $em->persist($oldSchedule);
  598.                         //rendre le nouveau planning indisponible si l'abo n'est pas canceled
  599.                         if ($subscriptionOrder->getIsCancelled() == true) {
  600.                             $newSchedule->setIsFree(true);
  601.                         } elseif ($subscriptionOrder->getIsCancelled() == false) {
  602.                             $newSchedule->setIsFree(false);
  603.                         } else {
  604.                             $newSchedule->setIsFree(false);
  605.                         }
  606.                         $em->persist($newSchedule);
  607.                         //ajouter le nouveau planning à l'abonnement
  608.                         $subscriptionOrder->addSchedule($newSchedule)
  609.                                           ->removeSchedule($oldSchedule);
  610.                         $em->persist($subscriptionOrder);
  611.                         //je récupère la date à laquelle le nouveau planning était marqué comme libre, ce sera la date du 1er cours de cette liste
  612.                         $startNewCourse            DateTimeImmutable::createFromMutable($newSchedule->getFreeDate());
  613.                         $newFreeDateForNewSchedule DateTimeImmutable::createFromMutable($newSchedule->getFreeDate());
  614.                         $nbOfCoursesToAdd sizeof($remainCourses);
  615.                         //ajouter les nouveaux cours à la table "PaidCoursesList", j'ajoute le même nombre qui est contenu dans le tableau des cours restant à l'abonnement (remainCourses)
  616.                         for ($i 0$i $nbOfCoursesToAdd$i++) {
  617.                             $newCourseDate $startNewCourse->modify('+'.$i.'weeks');
  618.                             $newPaidCourse $courseHelper->createNewCourse($newCourseDate$newSchedule$priceCourse);
  619.                             foreach ($holidays as $holiday) {
  620.                                 if ($newPaidCourse->getCourseDate() > $holiday->getStartAt() and $newPaidCourse->getCourseDate() < $holiday->getEndAt(
  621.                                     ) and $newPaidCourse->getIsCanceledForHoliday() === null) {
  622.                                     $newPaidCourse->setIsCanceledForHoliday(true);
  623.                                     $em->persist($newPaidCourse);
  624.                                 }
  625.                             }
  626.                             if ($newPaidCourse->getIsCanceledForHoliday() != true) {
  627.                                 $newPaidCourse->setIsCanceledForHoliday(false);
  628.                                 $em->persist($newPaidCourse);
  629.                             }
  630.                             $newPaidCourse
  631.                                 ->setSubscriptionOrder($subscriptionOrder)
  632.                                 ->setIsForGroup(false)
  633.                                 ->setSessionGroup(null)
  634.                                 ->setPaymentDate($paymentDate);
  635.                             if ($i == $nbOfCoursesToAdd 1) {
  636.                                 $nbOfWeekForFreeDate $nbOfCoursesToAdd 1;
  637.                                 $newSchedule->setFreeDate($newFreeDateForNewSchedule->modify('+'.$nbOfWeekForFreeDate.'weeks'));
  638.                             }
  639.                             $em->persist($newPaidCourse);
  640.                             $newSchedule->addCourseList($newPaidCourse);
  641.                             $subscriptionOrder->addCoursesList($newPaidCourse);
  642.                             $em->persist($newSchedule);
  643.                             $em->persist($subscriptionOrder);
  644.                         }
  645.                         //j'efface les anciens cours du oldPlanning de la table PaidCoursesList
  646.                         foreach ($remainCourses as $course) {
  647.                             $em->remove($course);
  648.                         }
  649.                     } else {
  650.                         $this->addFlash(
  651.                             'error',
  652.                             'Il ne vous reste plus de nouveaux cours à prendre pour pouvoir changer de professeur. Une fois vos nouveaux cours ajoutés (quand une nouvelle mensualité sera débitée) vous pourrez revenir sur cette page et changer de professeur.'
  653.                         );
  654.                         return $this->redirectToRoute(
  655.                             'user_subscription_show',
  656.                             [
  657.                                 'id'      => $subscriptionOrder->getId(),
  658.                                 '_locale' => $request->getLocale(),
  659.                             ]
  660.                         );
  661.                     }
  662.                 } else {
  663.                     $this->addFlash('error''Merci de choisir un nouveau planning pour remplacer TOUS vos anciens plannings');
  664.                     return $this->redirectToRoute(
  665.                         'subscription_change_teacher',
  666.                         [
  667.                             'id'      => $subscriptionOrder->getId(),
  668.                             'teacher' => $teacher->getId(),
  669.                             '_locale' => $request->getLocale(),
  670.                         ]
  671.                     );
  672.                 }
  673.             }
  674.             $subscriptionOrder->setUpdateAt(new \DateTimeImmutable())
  675.                               ->setTeacher($teacher);
  676.             $em->persist($subscriptionOrder);
  677.             $em->flush();
  678.             //Je compte le nb de cours annulé pour les vacances APRES le changement de planning
  679.             $newArrayCanceledCourseForHoliday $paidCourseListRepository->findNumberCanceledCourseForHolidayAfterScheduleChangeWithQuery($subscriptionOrder)->getQuery()->getArrayResult();;
  680.             $newNbCanceledCoursesForHoliday sizeof($newArrayCanceledCourseForHoliday);
  681.             if ($nbCanceledCoursesForHoliday != $newNbCanceledCoursesForHoliday) {
  682.                 $slackClient->notifyAdminNbCanceledCoursesForHolidayDoNotMatchAfterScheduleChange($subscriptionOrder$nbCanceledCoursesForHoliday$newNbCanceledCoursesForHoliday);
  683.             }
  684.             $subscriptionHelper->setLastCourse($subscriptionOrder);
  685.             $newTeacherEmail $teacher->getUserId()->getEmail();
  686.             $emailNotification->notifyStudentTeacherChange($subscriptionOrder$oldTeacher);
  687.             $slackClient->newSubscriptionNotifyTeacher($subscriptionOrder);
  688.             $slackClient->notifyTeacherStudentChangeTeacher($subscriptionOrder$oldTeacher);
  689.             //$slackClient->notifyAdminStudentChangeTeacher($subscriptionOrder, $oldTeacher);
  690.             $emailNotification->registrationSubscriptionNotifyTeacher($subscriptionOrder$newTeacherEmail);
  691.             $this->addFlash('success''Professeur modifié avec succes !');
  692.             return $this->redirectToRoute(
  693.                 'user_subscription_show',
  694.                 [
  695.                     'id'      => $subscriptionOrder->getId(),
  696.                     '_locale' => $request->getLocale(),
  697.                 ]
  698.             );
  699.         }
  700.         return $this->render(
  701.             'profil/change-teacher.html.twig',
  702.             [
  703.                 'subscription'  => $subscriptionOrder,
  704.                 'freeSchedules' => $freeSchedules,
  705.                 'teacher'       => $teacher,
  706.             ]
  707.         );
  708.     }
  709.     //TODO refacto pour code dupliquer à retravailler (spécialement avec la précédente méthode)
  710.     /**
  711.      * @Route("/{id}/schedule/edit", name="subscription_schedule_edit", methods={"POST"})
  712.      * @param SubscriptionOrder $subscriptionOrder
  713.      * @param Request $request
  714.      * @param PaidCourseListRepository $paidCourseListRepository
  715.      * @param TeacherScheduleRepository $teacherScheduleRepository
  716.      * @param EntityManagerInterface $em
  717.      * @param EmailNotification $emailNotification
  718.      * @param SlackClient $slackClient
  719.      * @param HolidayRepository $holidayRepository
  720.      * @param SubscriptionHelper $subscriptionHelper
  721.      * @param CourseHelper $courseHelper
  722.      *
  723.      * @return RedirectResponse
  724.      */
  725.     public function changeSubscriptionSchedule(SubscriptionOrder         $subscriptionOrderRequest $requestPaidCourseListRepository $paidCourseListRepository,
  726.                                                TeacherScheduleRepository $teacherScheduleRepositoryEntityManagerInterface $emEmailNotification $emailNotification,
  727.                                                SlackClient               $slackClientHolidayRepository $holidayRepositorySubscriptionHelper $subscriptionHelper,
  728.                                                CourseHelper              $courseHelper
  729.     ): RedirectResponse {
  730.         if ($request->isMethod('POST')) {
  731.             $roles $this->getUser()->getRoles();
  732.             if ($subscriptionHelper->hasCourseToday($subscriptionOrder) and ! in_array('ROLE_FR'$roles)) {
  733.                 $this->addFlash('error'"Vous avez cours aujourd'hui, vous ne pouvez donc pas changer de planning. Merci de modifier votre planning un jour où vous n'avez pas cours");
  734.                 return $this->redirectToRoute(
  735.                     'user_subscription_show',
  736.                     [
  737.                         'id'      => $subscriptionOrder->getId(),
  738.                         '_locale' => $request->getLocale(),
  739.                     ]
  740.                 );
  741.             }
  742.             //Je compte le nb de cours annulé pour les vacances avant le changement de planning
  743.             $arrayCanceledCourseForHoliday $paidCourseListRepository->findNumberCanceledCourseForHolidayAfterScheduleChangeWithQuery($subscriptionOrder)->getQuery()->getArrayResult();;
  744.             $nbCanceledCoursesForHoliday sizeof($arrayCanceledCourseForHoliday);
  745.             $holidays $holidayRepository->findAll();
  746.             $schedules $request->get('newSchedule');
  747.             $oldSchedules = [];
  748.             foreach ($schedules as $oldScheduleId => $newScheduleId) {
  749.                 if ($newScheduleId) {
  750.                     $oldSchedule $teacherScheduleRepository->findOneBy(['id' => $oldScheduleId]);
  751.                     $newSchedule $teacherScheduleRepository->findOneBy(['id' => $newScheduleId]);
  752.                     //Récupérer tout les cours qui ne seront pas fait :
  753.                     $remainCourses $paidCourseListRepository->findAllRemainCourseAfterScheduleChange($subscriptionOrder$oldSchedule);
  754.                     //permettre le changement de planning uniquement s'il reste des cours à prendre
  755.                     if ($remainCourses != null) {
  756.                         //Récupérer le prochain cours qui aurait du avoir lieu pour en faire la date de libération du oldPlanning (freeDate)
  757.                         $nextCourse $paidCourseListRepository->findNextCourseAfterScheduleChange($oldSchedule);
  758.                         $nextCourseDate DateTimeImmutable::createFromMutable($nextCourse->getCourseDate());
  759.                         //Je récupère la date de paiement de ce cours pour le réutiliser pour la nouveau planning, certain abo n'ont pas de paiement date car ce sont des ajout manuel, donc je code en défensive
  760.                         if ($nextCourse->getPaymentDate() != null) {
  761.                             $paymentDate $nextCourse->getPaymentDate();
  762.                         } else {
  763.                             $paymentDate null;
  764.                         }
  765.                         //Je récupère le montant du cours pour le réutiliser pour les nouveaux cours de la liste
  766.                         $priceCourse $nextCourse->getPrice();
  767.                         //Je récup les anciens plannings dans un tableau en dehors de la boucle pour pouvoir les envoyer par mail à l'élève.
  768.                         $oldSchedules[] = $oldSchedule;
  769.                         //Libérer l'ancien planning immédiatement
  770.                         $oldSchedule->setFreeDate($nextCourseDate)
  771.                                     ->setIsFree(true)
  772.                                     ->setSubscriptionOrder(null)
  773.                                     ->setOccupiedUntil(null);
  774.                         $em->persist($oldSchedule);
  775.                         //rendre le nouveau planning indisponible si l'abo n'est pas canceled
  776.                         if ($subscriptionOrder->getIsCancelled() == true) {
  777.                             $newSchedule->setIsFree(true);
  778.                         } elseif ($subscriptionOrder->getIsCancelled() == false) {
  779.                             $newSchedule->setIsFree(false);
  780.                         } else {
  781.                             $newSchedule->setIsFree(false);
  782.                         }
  783.                         $em->persist($newSchedule);
  784.                         //ajouter le nouveau planning à l'abonnement
  785.                         $subscriptionOrder->addSchedule($newSchedule)
  786.                                           ->removeSchedule($oldSchedule);
  787.                         $em->persist($subscriptionOrder);
  788.                         //je récupère la date à laquelle le nouveau planning était marqué comme libre, ce sera la date du 1er cours de cette liste
  789.                         $startNewCourse            DateTimeImmutable::createFromMutable($newSchedule->getFreeDate());
  790.                         $newFreeDateForNewSchedule DateTimeImmutable::createFromMutable($newSchedule->getFreeDate());
  791.                         $nbOfCoursesToAdd sizeof($remainCourses);
  792.                         //ajouter les nouveaux cours à la table "PaidCoursesList", j'ajoute le même nombre qui est contenu dans le tableau des cours restant à l'abonnement (remainCourses)
  793.                         for ($i 0$i $nbOfCoursesToAdd$i++) {
  794.                             $newCourseDate $startNewCourse->modify('+'.$i.'weeks');
  795.                             $newPaidCourse $courseHelper->createNewCourse($newCourseDate$newSchedule$priceCourse);
  796.                             foreach ($holidays as $holiday) {
  797.                                 if ($newPaidCourse->getCourseDate() > $holiday->getStartAt() and $newPaidCourse->getCourseDate() < $holiday->getEndAt(
  798.                                     ) and $newPaidCourse->getIsCanceledForHoliday() === null) {
  799.                                     $newPaidCourse->setIsCanceledForHoliday(true);
  800.                                     $em->persist($newPaidCourse);
  801.                                 }
  802.                             }
  803.                             if ($newPaidCourse->getIsCanceledForHoliday() != true) {
  804.                                 $newPaidCourse->setIsCanceledForHoliday(false);
  805.                                 $em->persist($newPaidCourse);
  806.                             }
  807.                             $newPaidCourse
  808.                                 ->setSubscriptionOrder($subscriptionOrder)
  809.                                 ->setIsForGroup(false)
  810.                                 ->setSessionGroup(null)
  811.                                 ->setPaymentDate($paymentDate);
  812.                             if ($i == $nbOfCoursesToAdd 1) {
  813.                                 $nbOfWeekForFreeDate $nbOfCoursesToAdd 1;
  814.                                 $newSchedule->setFreeDate($newFreeDateForNewSchedule->modify('+'.$nbOfWeekForFreeDate.'weeks'));
  815.                             }
  816.                             $em->persist($newPaidCourse);
  817.                             $newSchedule->addCourseList($newPaidCourse);
  818.                             $subscriptionOrder->addCoursesList($newPaidCourse);
  819.                             $em->persist($newSchedule);
  820.                             $em->persist($subscriptionOrder);
  821.                         }
  822.                         //j'efface les anciens cours du oldPlanning de la table PaidCoursesList
  823.                         foreach ($remainCourses as $course) {
  824.                             $em->remove($course);
  825.                         }
  826.                     } else {
  827.                         $this->addFlash('error''Il ne vous reste plus de nouveaux cours à prendre pour pouvoir changer de planning.');
  828.                         return $this->redirectToRoute(
  829.                             'user_subscription_show',
  830.                             [
  831.                                 'id'      => $subscriptionOrder->getId(),
  832.                                 '_locale' => $request->getLocale(),
  833.                             ]
  834.                         );
  835.                     }
  836.                 }
  837.             }
  838.             $subscriptionOrder->setUpdateAt(new \DateTimeImmutable());
  839.             $em->persist($subscriptionOrder);
  840.             $em->flush();
  841.             //Je compte le nb de cours annulé pour les vacances APRES le changement de planning
  842.             $newArrayCanceledCourseForHoliday $paidCourseListRepository->findNumberCanceledCourseForHolidayAfterScheduleChangeWithQuery($subscriptionOrder)->getQuery()->getArrayResult();;
  843.             $newNbCanceledCoursesForHoliday sizeof($newArrayCanceledCourseForHoliday);
  844.             if ($nbCanceledCoursesForHoliday != $newNbCanceledCoursesForHoliday) {
  845.                 $slackClient->notifyAdminNbCanceledCoursesForHolidayDoNotMatchAfterScheduleChange($subscriptionOrder$nbCanceledCoursesForHoliday$newNbCanceledCoursesForHoliday);
  846.             }
  847.             $subscriptionHelper->setLastCourse($subscriptionOrder);
  848.             $emailNotification->notifyStudentSubscriptionSchedulesChange($subscriptionOrder$oldSchedules);
  849.             $emailNotification->notifyTeacherSubscriptionScheduleChange($subscriptionOrder$oldSchedules);
  850.             $slackClient->notifyTeacherChangeScheduleSubscription($subscriptionOrder);
  851.             $this->addFlash('success''Planning modifié avec succes !');
  852.             return $this->redirectToRoute(
  853.                 'user_subscription_show',
  854.                 [
  855.                     'id'      => $subscriptionOrder->getId(),
  856.                     '_locale' => $request->getLocale(),
  857.                 ]
  858.             );
  859.         }
  860.     }
  861. }