<?php
namespace App\Controller\LevelTest;
use App\Entity\Gender;
use App\Entity\Holiday;
use App\Entity\PaidCourseList;
use App\Entity\Subject;
use App\Entity\UserPlacementTest;
use App\Helper\CourseHelper;
use App\Helper\LevelPlacementTestHelper;
use App\Notification\EmailNotification\LevelTestEmailNotification;
use App\Notification\SlackNotification\LevelTestSlackNotification;
use App\Order\OrderHelper;
use App\Repository\ChildRepository;
use App\Repository\HolidayRepository;
use App\Repository\PaidCourseListRepository;
use App\Repository\SessionOrderRepository;
use App\Repository\SessionRegistrationDateRepository;
use App\Repository\SubjectRepository;
use App\Repository\TeacherRepository;
use App\Repository\TeacherScheduleRepository;
use App\Repository\UserPlacementTestRepository;
use App\Repository\UserRepository;
use App\Service\ActiveCampaignHelper;
use App\Service\Currency\CurrencyChangeService;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/user/placement/test")
* @Security("is_granted('ROLE_USER')")
*/
class LevelTestController extends AbstractController
{
/**
* @Route("/{gender}/{tag}", name="test_placement", defaults={"tag": "alKaamil"}, methods={"GET","POST"})
* @ParamConverter("gender", options={"mapping": {"gender" : "name"}})
* @param Gender $gender
* @param $tag
* @param SubjectRepository $subjectRepository
* @param Request $request
* @param TeacherRepository $teacherRepository
* @param OrderHelper $orderHelper
* @param TeacherScheduleRepository $teacherScheduleRepository
* @param LevelPlacementTestHelper $levelPlacementTestHelper
* @param SessionOrderRepository $sessionOrderRepository
* @param UserRepository $userRepository
* @param UserPlacementTestRepository $userPlacementTestRepository
* @return RedirectResponse|Response
*/
public function placementTest(Gender $gender, $tag, SubjectRepository $subjectRepository, Request $request, TeacherRepository $teacherRepository, OrderHelper $orderHelper,
TeacherScheduleRepository $teacherScheduleRepository, LevelPlacementTestHelper $levelPlacementTestHelper, SessionOrderRepository $sessionOrderRepository,
UserRepository $userRepository, UserPlacementTestRepository $userPlacementTestRepository, SessionRegistrationDateRepository $sessionRegistrationDateRepository,
ChildRepository $childRepository, HolidayRepository $holidayRepository, CurrencyChangeService $currencyChangeService)
{
$free = false;
$hadPurchasedTest = null;
/** @var Holiday $holiday */
$holiday = $holidayRepository->findBy([
'name' => 'Ramadan'
]);
$startHoliday = $holiday[0]->getStartAt();
$endHoliday = $holiday[0]->getEndAt();
$currentDate = new \DateTime();
$subject = $subjectRepository->findOneBy([
'tagName' => $tag
]);
$limitRegistrationDateForSubject = $sessionRegistrationDateRepository->findOneBy([
'subject' => $subject
]);
$limitRegistrationDate = $limitRegistrationDateForSubject->getCloseRegistrationDate();
$programName = $request->getLocale() == 'fr' ? $subject->getName() : $subject->getNameEn();
$email = strtolower($request->query->get('email'));
$sessionOrderId = $request->get('sessionorderid');
if ($email){
$user = $userRepository->findOneBy([
'email' => $email
]);
$currentSessionOrder = $sessionOrderRepository->getCurrentSessionOrderForOneUserForPlacementTest($sessionOrderId, $tag);
if ($userPlacementTestRepository->findTestWithoutDate()){
$hadPurchasedTestArray = $userPlacementTestRepository->findTestWithoutDate();
foreach ($hadPurchasedTestArray as $element ) {
if ( $email == $element->getUser()->getEmail() ) {
$hadPurchasedTest = $element;
}
}
$free = true;
}
if (!$currentSessionOrder and !$hadPurchasedTest){
$this->addFlash('error', "Vous ne pouvez pas réserver un test gratuitement, merci de contacter le secretariat");
return $this->redirectToRoute('user_dashboard', [
'_locale' => $request->getLocale()
]);
}
}else{
$user = $this->getUser();
$currentSessionOrder =$sessionOrderRepository->getNewSessionOrderForOneUserForPlacementTest($user, $tag);
}
if ($currentSessionOrder){
$havePlacementTestForThisOrder = $userPlacementTestRepository->findOneBy([
'sessionOrder' => $currentSessionOrder,
'participant' => $currentSessionOrder->getParticipant(),
'isCanceledbyUs' => false
]);
if ($havePlacementTestForThisOrder){
$this->addFlash('error', "Vous avez déjà réservé un test de niveau pour cette session");
return $this->redirectToRoute('user_dashboard', [
'_locale' => $request->getLocale()]);
}else{
$free = true;
}
$wasInPreviousSession = $sessionOrderRepository->findStudentInPreviousSession($user, $tag);
if ($wasInPreviousSession){
$this->addFlash('error', "Vous étiez déjà élève d'une précédente session, vous n'avez donc pas besoin de passer un test de niveau (Sauf si vous n'avez pas assisté au test de fin de session et devez valider votre niveau pour la prochaine session).");
$free = false;
}
}
//TODO trouver si élève est inscrit à un groupe
//TODO Definir si son inscription correspond bien à la dernière période (ou date debut de session plus petite que date du jour)
//TODO définir s'il n'a pas déjà un testPlacement pour cette sessionOrder (canceledbyUs false, si c'est canceldbyus true il aura droit d'acceder pour reprendre un RDV)
if (!$subject){
$this->addFlash('error', "Le programme demandé n'existe pas");
return $this->redirectToRoute('user_dashboard', [
'_locale' => $request->getLocale()
]);
}
if ($currentDate > $startHoliday and $currentDate < $endHoliday) {
$freeTeachers = $teacherRepository->findTeachersWithFreeSchedulesBySubjectAndGenderForTestForRamadan( $subject->getId(), $gender->getId());
}else{
$freeTeachers = $teacherRepository->findTeachersWithFreeSchedulesBySubjectAndGenderForTest( $subject->getId(), $gender->getId(), $limitRegistrationDate);
}
$currency = $currencyChangeService->getCurrencyChangeForView($request);
$error = false;
$price = round(7 * $currency['currencyRate']);
if ($request->isMethod('POST')) {
$token = $request->request->get('stripeToken');
$chosenScheduleId = $request->request->get('teacherScheduleId');
if (isset($currentSessionOrder)){
$participant = $currentSessionOrder->getParticipant();
}else {
//$participant = $request->request->get('participant');
$currentSessionOrder = null;
$selectedStudentId= $request->request->get('select-student');
if ($selectedStudentId == $user->getId()){
$participant = null;
}else{
$participant = $childRepository->findOneBy([
'id' => $selectedStudentId
]);
}
}
if (!$chosenScheduleId){
$this->addFlash('error', 'Merci de choisir un horaire');
if ($email){
return $this->redirectToRoute('test_placement', [
'gender' => $gender,
'tag' => $tag,
'email' => $email,
'sessionorderid' => $sessionOrderId,
'_locale' => $request->getLocale()
]);
}else{
return $this->redirectToRoute('test_placement', [
'gender' => $gender,
'tag' => $tag,
'_locale' => $request->getLocale()
]);
}
}
$chosenSchedule = $teacherScheduleRepository->findOneBy(['id' => $chosenScheduleId]);
if ($free == false){
try {
$invoice = $orderHelper->chargeLevelTest($token, $price, $chosenSchedule, $user);
$stripeCustomerId = $invoice->customer;
} 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;
}
}else{
$stripeCustomerId = "free";
$price = 0;
}
if (!$error){
if ($hadPurchasedTest){
$userPlacementTest = $hadPurchasedTest;
}else{
$userPlacementTest = $levelPlacementTestHelper->createLevelPlacementTestInDatabase($stripeCustomerId,$user, $price, $subject, $participant, $currentSessionOrder);
}
$levelTestCourse = $levelPlacementTestHelper->createNewCourseForTest($chosenSchedule,$userPlacementTest);
//add 1 week to chosen schedule
$levelPlacementTestHelper->addOneWeekToChosenSchedule($chosenSchedule);
//Send notifications To student and admin
$levelPlacementTestHelper->sendNotifications($userPlacementTest, $levelTestCourse);
/*
$activeCampaignContact = $activeCampaignHelper->getOrCreateContact($userPlacementTest);
$activeCampaignHelper->addTagsToContact(["buy".$tag."Test"], $activeCampaignContact);
*/
//TODO MODIFIER AFFICHAGE DASHBOARD ADMIN ET PROF **OKKK**
//TODO PAGE MODIF NIVEAU APRES TEST (A LA PLACE DU RAPPORT DE COURS) **OKKK**
//TODO VOIR COMMENT FAIRE POUR BOOKER TEST SANS PAYER (SI ENVOI DIRECTEMEMENT PAR EMAIL) **OKKK**
//TODO MODIFIER PAGE COURSES POUR AFFICHIER TEST NIVEAU **OKKK**
//TODO PAGE MODIFIER RESERVATION (+ 24H) **OKKK**
//TODO MODIFIER EMAIL ENVOI CONFIRMATION COURS COLLECTIF POUR RESERVER UN TEST DE NIVEAU (SI PAS DEJA FAIT ET SI A PAS FAIT SON EXAM A LA PRECEDENTE SESSION) **OKKK** --A améliorer avec un email séparé en flitrant pour envoyer uniquement à la bonne personne--
//TODO ENVOI EMAIL RESULTAT À L'ELEVE **OKKK***
//TODO CRONMAIL POUR RAPPEL RESULTAT PAS DONNÉ **OKKK***
//TODO TESTER ACHAT TOUS LES COURS POUR VOIR SI RIEN DE CASSÉ
$this->addFlash('success', "Votre test a été reservé avec succes !");
return $this->redirectToRoute('user_courses', [
'_locale' => $request->getLocale()
]);
}else{
$this->addFlash('error', $error);
return $this->redirectToRoute('test_placement', [
'gender' => $gender,
'tag' => $tag,
'_locale' => $request->getLocale()
]);
}
}
return $this->render('user_placement_test/book.html.twig', [
'subject' => $subject,
'teachers' => $freeTeachers,
'stripe_public_key' => $this->getParameter('stripe_public_key'),
'errorCard' => $error,
'price' => $price,
'free' => $free,
'dateLimitForTest' => $limitRegistrationDate ? $limitRegistrationDate->format('Y-m-d H:i') : new \DateTime('Y-m-d H:i'),
'dateLimitRegistration' => $limitRegistrationDateForSubject,
'user' => $this->getUser(),
'currency' => $currency
]);
}
/**
* @Route("/{gender}/{tag}/{testId}/{courseId}/edit", name="test_placement_edit")
* @ParamConverter("gender", options={"mapping": {"gender" : "name"}})
* @param Gender $gender
* @param Subject $subject
* @param UserPlacementTest $userPlacementTest
* @param PaidCourseList $courseList
* @param TeacherRepository $teacherRepository
* @param Request $request
* @param TeacherScheduleRepository $teacherScheduleRepository
* @param LevelPlacementTestHelper $levelPlacementTestHelper
* @return RedirectResponse|Response
*/
public function editLevelTestSchedule(Gender $gender,$tag, $testId, $courseId, TeacherRepository $teacherRepository, Request $request, TeacherScheduleRepository $teacherScheduleRepository, LevelPlacementTestHelper $levelPlacementTestHelper, SubjectRepository $subjectRepository, UserPlacementTestRepository $userPlacementTestRepository, PaidCourseListRepository $paidCourseListRepository, SessionRegistrationDateRepository $sessionRegistrationDateRepository)
{
$free = true;
$price = 0;
$error = null;
$userPlacementTest = $userPlacementTestRepository->findOneBy([
'id' => $testId
]);
$oldLevelTestCourse = $paidCourseListRepository->findOneBy([
'id' => $courseId
]);
if (!$oldLevelTestCourse or !$userPlacementTest){
$this->addFlash('error', 'Aucun test trouvé, contactez le secrétariat');
return $this->redirectToRoute('user_courses', [
'_locale' => $request->getLocale()
]);
}
$currentDate = new \DateTime();
$courseDate = DateTimeImmutable::createFromMutable($oldLevelTestCourse->getCourseDate());
$limit = $courseDate->modify('-1 day');
if ($currentDate > $limit and $oldLevelTestCourse->getIsCanceled() == false){
$this->addFlash('error', 'Il est trop tard pour modifier le rendez-vous. Celui-ci aura lieu dans moins de 24h');
return $this->redirectToRoute('user_courses', [
'_locale' => $request->getLocale()
]);
}
$subject = $subjectRepository->findOneBy([
'tagName' => $tag
]);
$limitRegistrationDateForSubject = $sessionRegistrationDateRepository->findOneBy([
'subject' => $subject
]);
$limitRegistrationDate = $limitRegistrationDateForSubject->getCloseRegistrationDate();
$freeTeachers = $teacherRepository->findTeachersWithFreeSchedulesBySubjectAndGenderForTest( $subject->getId(), $gender->getId(), $limitRegistrationDate);
if ($request->isMethod('POST')) {
$chosenScheduleId = $request->request->get('teacherScheduleId');
if (!$chosenScheduleId){
$this->addFlash('error', 'Merci de choisir un horaire');
return $this->redirectToRoute('test_placement_edit', [
'gender' => $gender,
'tag' => $subject->getTagName(),
'testId' => $testId,
'courseId' => $courseId,
'_locale' => $request->getLocale()
]);
}
$chosenSchedule = $teacherScheduleRepository->findOneBy(['id' => $chosenScheduleId]);
$levelTestCourse = $levelPlacementTestHelper->createNewCourseForTest($chosenSchedule,$userPlacementTest);
//add 1 week to chosen schedule
$levelPlacementTestHelper->addOneWeekToChosenSchedule($chosenSchedule);
//delete old testCourse + remette planning à dispo
$levelPlacementTestHelper->deleteOldTestCourse($oldLevelTestCourse);
//Send notifications To student and admin
$levelPlacementTestHelper->sendNotifications($userPlacementTest, $levelTestCourse, $oldLevelTestCourse);
$this->addFlash('success', "Votre rendez-vous a été modifié avec succes !");
return $this->redirectToRoute('user_courses', [
'_locale' => $request->getLocale()
]);
}
return $this->render('user_placement_test/book.html.twig', [
'subject' => $subject,
'teachers' => $freeTeachers,
'stripe_public_key' => $this->getParameter('stripe_public_key'),
'errorCard' => $error,
'price' => $price,
'free' => $free,
]);
}
}