src/Controller/CourseController.php line 745

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Person;
  4. use App\Entity\Category;
  5. use App\Entity\Course;
  6. use App\Entity\Order;
  7. use App\Entity\CourseData;
  8. use App\Entity\Invoice;
  9. use App\Entity\Textblocks;
  10. use App\Form\CourseType;
  11. use App\Repository\CourseFieldRepository;
  12. use App\Repository\CourseDataRepository;
  13. use App\Service\PdfService;
  14. use App\Form\CourseImagesType;
  15. use App\Service\MailerService;
  16. use App\Service\InvoiceService;
  17. use App\Service\SepaXmlService;
  18. use App\Service\PaymentService;
  19. use App\Entity\InvoicePayment;
  20. use App\Entity\CourseOccurrence;
  21. use App\Repository\TagsRepository;
  22. use App\Repository\TagsPersonRepository;
  23. use App\Repository\PersonRepository;
  24. use App\Entity\OrderItem;
  25. use App\Repository\ClientConfigRepository;
  26. use App\Repository\OrderRepository;
  27. use App\Repository\CourseRepository;
  28. use App\Service\EmailHistoryService;
  29. use App\Service\ConfigurationService;
  30. use App\Repository\CartItemRepository;
  31. use App\Entity\CustomerHistoryEntry;
  32. use App\Service\CustomerHistoryService;
  33. use Doctrine\ORM\EntityManagerInterface;
  34. use App\Repository\TextblocksRepository;
  35. use App\Repository\WaitItemRepository;
  36. use App\Repository\OrderItemRepository;
  37. use App\Service\Exception\ServiceException;
  38. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  39. use App\Repository\CourseOccurrenceRepository;
  40. use App\Repository\InvoiceItemRepository;
  41. use App\Repository\InvoiceRepository;
  42. use App\Service\OrderService;
  43. use Symfony\Component\HttpFoundation\Response;
  44. use Symfony\Component\HttpFoundation\Request;
  45. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  46. use Symfony\Component\Routing\Annotation\Route;
  47. use Doctrine\Common\Collections\ArrayCollection;
  48. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  49. use Menke\UserBundle\Controller\AbstractClientableController;
  50. use Menke\UserBundle\Repository\ClientRepository;
  51. /**
  52.  * @Route("/course")
  53.  * @IsGranted("ROLE_SPEAKER")
  54.  */
  55. class CourseController extends AbstractClientableController
  56. {
  57.     const LISTING_LIMIT 25;
  58.     /**
  59.      *
  60.      */
  61.     private function getListingLimit(): int
  62.     {
  63.         return !empty($_ENV['COURSES_LISTINGLIMIT']) ? (int) $_ENV['COURSES_LISTINGLIMIT'] : 20;
  64.     }
  65.     /**
  66.      * @Route("/", name="course_index", methods="GET")
  67.      */
  68.     public function index(
  69.         Request $request,
  70.         \App\Service\UiService $uiService,
  71.         CourseRepository $courseRepository,
  72.         EntityManagerInterface $manager,
  73.     ): Response {
  74.         $order $uiService->getSortOrder('course-index-listing');
  75.         $archive = !empty($request->get('archive'));
  76.         $courses $courseRepository->getCoursesByClientPaged(
  77.             $this->getCurrentClient(),
  78.             $this->getListingLimit(),
  79.             $order['orderDirection'] ?? 'ASC',
  80.             $order['orderBy'] ?? 'title',
  81.             1,
  82.             $archive,
  83.         );
  84.         // die Anzahl der Kurse mit den gebuchten überprüfen und die bookedSlots bei den CourseOccurreces aktualisieren
  85.         $this->manager $manager;
  86.         foreach ($courses as $course
  87.         {
  88.             foreach ($course->getOccurrences() as $occurrence
  89.                         {
  90.                             $occurrence->setBookedSlots($occurrence->getBookedSlots());
  91.                             $this->manager->persist($occurrence);
  92.                         }
  93.          }
  94.          $this->manager->flush();
  95.          ///////////////////////////////////////////
  96.         return $this->render('course/index.html.twig', [
  97.             'uiService' => $uiService,
  98.             'courses' =>  $courses,
  99.             'total' => $courses->count(),
  100.             'pages' => ceil($courses->count() / $this->getListingLimit()),
  101.             'page' => 1,
  102.             'archive' => $archive,
  103.             'env' => $_ENV,
  104.         ]);
  105.     }
  106.     /**
  107.      * @Route("/{page}/{orderby}/{order}", name="course_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
  108.      */
  109.     public function indexListing(
  110.         Request $request,
  111.         CourseRepository $courseRepository,
  112.         \App\Service\UiService $uiService,
  113.         $page,
  114.         $orderby,
  115.         $order
  116.     ): Response {
  117.         $uiService->storeSortOrder('course-index-listing'$orderby$order);
  118.         $archive = !empty($request->get('archive'));
  119.         $courses $courseRepository->getCoursesByClientPaged($this->getCurrentClient(), $this->getListingLimit(), $order$orderby$page$archive);
  120.         return $this->render('course/_index_listing.html.twig', [
  121.             'courses' => $courses,
  122.             'total' => $courses->count(),
  123.             'pages' => ceil($courses->count() / $this->getListingLimit()),
  124.             'page' => $page,
  125.             'archive' => $archive,
  126.             'env' => $_ENV,
  127.         ]);
  128.     }
  129.     /**
  130.      * @Route("/new", name="course_new", methods="GET|POST")
  131.      */
  132.     public function new(Request $requestConfigurationService $configService): Response
  133.     {
  134.         $course = new Course();
  135.         if (!empty($courseNature $request->get('courseNature'))) {
  136.             $course->setCourseNature($courseNature);
  137.         }
  138.         $form $this->createForm(CourseType::class, $course, [
  139.             'client' => $this->getCurrentClient(),
  140.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  141.         ]);
  142.         $form->handleRequest($request);
  143.         if ($form->isSubmitted() && $form->isValid()) {
  144.             $course->setClient($this->getCurrentClient());
  145.             $course->setNumber($configService->getNewCourseNumberByClient($this->getCurrentClient()));
  146.             foreach ($course->getTexts() as $key => $text) {
  147.                 $text->setCreated(new \DateTime());
  148.                 if (empty($text->getOrderId())) {
  149.                     $text->setOrderId($key 1000);
  150.                 }
  151.             }
  152.             $em $this->getDoctrine()->getManager();
  153.             $course->setCreated(new \DateTime());
  154.             $em->persist($course);
  155.             $em->flush();
  156.             $this->addFlash('success''Kurs angelegt');
  157.             return $this->redirectToRoute('course-occurrence_new', ['courseId' => $course->getId()]);
  158.         }
  159.         return $this->render('course/new.html.twig', [
  160.             'course' => $course,
  161.             'fields' => null,
  162.             'form' => $form->createView(),
  163.         ]);
  164.     }
  165.     /**
  166.      * @Route("/{id}/edit", name="course_edit", methods="GET|POST", requirements={"id"="\d+"})
  167.      */
  168.     public function edit(
  169.         Request $request,
  170.         Course $course,
  171.         ConfigurationService $configService,
  172.         CourseFieldRepository $courseFieldRepository,
  173.         CourseDataRepository $courseDataRepository
  174.     ): Response {
  175.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  176.         $courseTexts = new ArrayCollection();
  177.         foreach ($course->getTexts() as $text) {
  178.             $courseTexts->add($text);
  179.         }
  180.         $form $this->createForm(CourseType::class, $course, [
  181.             'client' => $this->getCurrentClient(),
  182.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  183.         ]);
  184.         $form->handleRequest($request);
  185.         if ($form->isSubmitted() && $form->isValid()) {
  186.             $manager $this->getDoctrine()->getManager();
  187.             foreach ($courseTexts as $text) {
  188.                 if (false === $course->getTexts()->contains($text)) {
  189.                     $text->setCourse(null);
  190.                     $manager->remove($text);
  191.                 }
  192.             }
  193.             foreach ($course->getTexts() as $key => $text) {
  194.                 if (empty($text->getOrderId())) {
  195.                     $text->setCreated(new \DateTime());
  196.                     $text->setOrderId($key 1000);
  197.                 }
  198.                 $text->setModified(new \DateTime());
  199.             }
  200.             $fields $request->request->get('fields');
  201.             if (!is_null($fields)) {
  202.                 foreach ($fields as $fieldId => $value) {
  203.                     $field $courseFieldRepository->find($fieldId);
  204.                     $data $courseDataRepository->findBy([
  205.                         'course' => $course,
  206.                         'field' => $field,
  207.                     ]);
  208.                     if (count($data) == 0) {
  209.                         $data = new CourseData();
  210.                         $data->setClient($this->getCurrentClient());
  211.                         $data->setCourse($course);
  212.                         $data->setField($field);
  213.                         $data->setCreated(new \datetime());
  214.                         $manager->persist($data);
  215.                     } else {
  216.                         $data $data[0];
  217.                     }
  218.                     $data->setValueText($value);
  219.                     $data->setModified(new \datetime());
  220.                 }
  221.             } else {
  222.                 $fields = [];
  223.             }
  224.             $course->setModified(new \datetime());
  225.             $manager->flush();
  226.             $this->addFlash('notice''Kurs gespeichert');
  227.             return $this->redirectToRoute('course_edit', ['id' => $course->getId()]);
  228.         }
  229.         // Fetch course fields
  230.         $sql 'SELECT
  231.             f.*,
  232.             d.value_text,
  233.             d.value_integer,
  234.             d.value_date
  235.         FROM
  236.             course_field f
  237.         LEFT JOIN
  238.             course_data d
  239.         ON 
  240.             d.field_id = f.id AND
  241.             d.course_id = ' $course->getId();
  242.         $em $this->getDoctrine()->getManager();
  243.         $stmt $em->getConnection()->prepare($sql);
  244.         $stmt->execute();
  245.         $result $stmt->fetchAll();
  246.         $fields = [];
  247.         $isset false;
  248.         foreach ($result as $field) {
  249.             $isset false;
  250.             if (!empty($field['category'])) {
  251.                 if (!$course->getCategory()) {
  252.                     continue;
  253.                 }
  254.                 if (!in_array($course->getCategory()->getId(), json_decode($field['category'], true))) {
  255.                     continue;
  256.                 } else {
  257.                     $field $this->createDescription($field'course');
  258.                     $isset true;
  259.                 }
  260.             }
  261.             if (!empty($field['course_type'])) {
  262.                 if (!$course->getType()) {
  263.                     continue;
  264.                 }
  265.                 if (!in_array($course->getType()->getId(), json_decode($field['course_type'], true))) {
  266.                     continue;
  267.                 } else {
  268.                     if (!$isset) {
  269.                         $field $this->createDescription($field'course');
  270.                         $isset true;
  271.                     }
  272.                 }
  273.             }
  274.             if (empty($field['category']) && empty($field['ourse_type']) && !empty($field['certificate'])) {
  275.                 if (!$isset$field $this->createDescription($field'certificate');
  276.             }
  277.             if (
  278.                 !empty($field['category']) ||
  279.                 !empty($field['course_type']) ||
  280.                 $field['certificate']
  281.             ) {
  282.                 $fields[] = $field;
  283.             }
  284.         }
  285.         return $this->render('course/edit.html.twig', [
  286.             'course' => $course,
  287.             'form' => $form->createView(),
  288.             'fields' => $fields,
  289.             'env' => $_ENV,
  290.         ]);
  291.     }
  292.     /**
  293.      * @Route("/{id}", name="course_delete", methods="DELETE", requirements={"id"="\d+"})
  294.      */
  295.     public function delete(Request $requestCourse $course): Response
  296.     {
  297.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  298.         if ($this->isCsrfTokenValid('delete' $course->getId(), $request->request->get('_token'))) {
  299.             $em $this->getDoctrine()->getManager();
  300.             $em->remove($course);
  301.             try {
  302.                 $em->flush();
  303.             } 
  304.             catch (\Exception $e
  305.             {
  306.                 $errorMessage $e->getMessage();
  307.                 if (str_contains($errorMessage'Integrity constraint violation'))
  308.                 {
  309.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.');
  310.        //         $this->addFlash('error', $errorMessage); 
  311.                 
  312.                 else 
  313.                 {
  314.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.'); 
  315.                 }
  316.                return $this->redirectToRoute('course_index');
  317.             }
  318.         $this->addFlash('notice''Kurs gelöscht');
  319.         }
  320.         return $this->redirectToRoute('course_index');
  321.     }
  322.     /**
  323.      * @Route("/multiple", name="course_delete-multiple", methods="DELETE")
  324.      */
  325.     public function deleteMultiple(
  326.         Request $request,
  327.         CourseRepository $courseRepo,
  328.         CartItemRepository $cartItemRepo,
  329.         WaitItemRepository $waitItemRepo,
  330.         OrderItemRepository $orderItemRepo
  331.     ): Response {
  332.         if ($this->isCsrfTokenValid('delete_courses'$request->request->get('_token'))) {
  333.             $em $this->getDoctrine()->getManager();
  334.             $deleteIds $request->request->get('delete');
  335.             foreach ($deleteIds as $id => $value) {
  336.                 if ($value) {
  337.                     $course $courseRepo->find($id);
  338.                     $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  339.                     $waitItems $waitItemRepo->findBy(['course' => $course]);
  340.                     foreach ($waitItems as $waitItem) {
  341.                         $em->remove($waitItem);
  342.                     }
  343.                     $cartItems $cartItemRepo->findBy(['course' => $course]);
  344.                     foreach ($cartItems as $cartItem) {
  345.                         $em->remove($cartItem);
  346.                     }
  347.                     $orderItems $orderItemRepo->findBy(['course' => $course]);
  348.                     foreach ($orderItems as $orderItem) {
  349.                         $orderItem->setCourseOccurrence(null);
  350.                     }
  351.                     $em->remove($course);
  352.                 }
  353.             }
  354.             try {
  355.                 $em->flush();
  356.             } catch (\Exception $e) {
  357.                 $errorMessage $e->getMessage();
  358.                 if (str_contains($errorMessage'Integrity constraint violation')){
  359.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.');
  360.        //         $this->addFlash('error', $errorMessage); 
  361.                 } else {
  362.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.'); 
  363.                 }
  364.                return $this->redirectToRoute('course_index');
  365.                
  366.             }
  367.             
  368.             $this->addFlash('notice'count($deleteIds) > 'Kurse gelöscht' 'Kurs gelöscht');
  369.         }
  370.         return $this->redirectToRoute('course_index');
  371.     }
  372.     /**
  373.      * @Route("/{id}/occurrences", name="course_occurrences", methods="GET", requirements={"id"="\d+"})
  374.      */
  375.     public function courseOccurrences(
  376.         Request $request,
  377.         Course $course,
  378.         CourseOccurrenceRepository $repo,
  379.         \App\Service\UiService $uiService
  380.     ): Response {
  381.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  382.         $order $uiService->getSortOrder('course-occurrences-listing');
  383.         $archive = !empty($request->get('archive'));
  384.         $occurrences $repo->findByCoursePaged(
  385.             $course,
  386.             self::LISTING_LIMIT,
  387.             $order['orderDirection'] ?? 'ASC',
  388.             $order['orderBy'] ?? 'title'
  389.         );
  390.         return $this->render('course/occurrences.html.twig', [
  391.             'uiService' => $uiService,
  392.             'course' => $course,
  393.             'occurrences' => $occurrences->getIterator(),
  394.             'total' => $occurrences->count(),
  395.             'pages' => ceil($occurrences->count() / self::LISTING_LIMIT),
  396.             'page' => 1,
  397.             'env' => $_ENV,
  398.             'archive' => $archive,
  399.         ]);
  400.     }
  401.     /**
  402.      * @Route("/{id}/occurrences/{page}/{orderby}/{order}/{search}", name="course_occurrences_listing", methods="GET", defaults={"search"="", "order"="desc", "orderby"="start"}, requirements={"id"="\d+"})
  403.      */
  404.     public function courseOccurrencesListing(
  405.         Request $request,
  406.         Course $course,
  407.         $page,
  408.         $orderby,
  409.         $order,
  410.         $search,
  411.         CourseOccurrenceRepository $repo,
  412.         \App\Service\UiService $uiService
  413.     ): Response {
  414.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  415.         $uiService->storeSortOrder('course-occurrences-listing'$orderby$order);
  416.         $occurrences $repo->findByCoursePaged($courseself::LISTING_LIMIT$order$orderby$page$search);
  417.         return $this->render('course/tabs/_occurrences_listing.html.twig', [
  418.             'course' => $course,
  419.             'occurrences' => $occurrences->getIterator(),
  420.             'total' => $occurrences->count(),
  421.             'pages' => ceil($occurrences->count() / self::LISTING_LIMIT),
  422.             'page' => $page,
  423.             'env' => $_ENV,
  424.         ]);
  425.     }
  426.     /**
  427.      * @Route("/{id}/images", name="course_images", methods="GET|POST", requirements={"id"="\d+"})
  428.      */
  429.     public function courseImages(Request $requestCourse $course)
  430.     {
  431.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  432.         $courseImages = new ArrayCollection();
  433.         foreach ($course->getImages() as $image) {
  434.             $courseImages->add($image);
  435.         }
  436.         $form $this->createForm(CourseImagesType::class, $course);
  437.         $form->handleRequest($request);
  438.         if ($form->isSubmitted() && $form->isValid()) {
  439.             $manager $this->getDoctrine()->getManager();
  440.             foreach ($courseImages as $image) {
  441.                 if (false === $course->getImages()->contains($image)) {
  442.                     $image->setCourse(null);
  443.                     $manager->remove($image);
  444.                 }
  445.             }
  446.             foreach ($course->getImages() as $key => $image) {
  447.                 if (empty($image->getOrderId())) {
  448.                     $image->setOrderId($key 1000);
  449.                 }
  450.             }
  451.             $image->setCreated(new \Datetime());
  452.             $manager->flush();
  453.             $this->addFlash('notice''Kursbilder gespeichert');
  454.             return $this->redirectToRoute('course_images', ['id' => $course->getId()]);
  455.         }
  456.         return $this->render('course/images.html.twig', [
  457.             'course' => $course,
  458.             'form' => $form->createView(),
  459.             'env' => $_ENV,
  460.         ]);
  461.     }
  462.     /**
  463.      * @Route("/{id}/invoices", name="course_invoices", methods="GET", requirements={"id"="\d+"})
  464.      */
  465.     public function courseInvoices(
  466.         Request $request,
  467.         Course $course,
  468.         OrderItemRepository $repo,
  469.         OrderService $orderService,
  470.         TagsPersonRepository  $tagsPersonRepository,
  471.     ) {
  472.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  473.         $orderItems $repo->findByCoursePaged($course);
  474.         /**
  475.          * The display logic of subscription courses is different, as there only one order exists per
  476.          * customer/participant, but they should appear in every following course occurrence until they cancel.
  477.          */
  478.         // if ($course->getCourseNature() === 'CourseSubscription') {
  479.         //     return $this->render('course/invoices-subscription.html.twig', [
  480.         //         'course' => $course,
  481.         //         'orderItems' => $orderItems->getIterator(),
  482.         //     ]);
  483.         // } else {
  484.         $archive = !empty($request->get('archive'));
  485.         if ($course->getCourseNature() === 'CourseSubscription') {
  486.             foreach ($orderItems as $orderItem) {
  487.                 $orderItem->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem);
  488.             }
  489.         }
  490.         return $this->render('course/invoices.html.twig', [
  491.             'tagsPerson' => $tagsPersonRepository->findAll(),
  492.             'course' => $course,
  493.             'orderItems' => $orderItems->getIterator(),
  494.             'archive' => $archive,
  495.         ]);
  496.         // }
  497.     }
  498.     /**
  499.      * @Route("/{id}/invoices/create", name="course_create_invoices", methods="POST", requirements={"id"="\d+"})
  500.      */
  501.     public function courseCreateInvoices(
  502.         Request $request,
  503.         Course $course,
  504.         OrderItemRepository $itemRepo,
  505.         InvoiceService $invoiceService
  506.     ) {
  507.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  508.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  509.             $em $this->getDoctrine()->getManager();
  510.             $createIds $request->request->get('create');
  511.             $count 0;
  512.             if (!empty($createIds)) {
  513.                 foreach ($createIds as $id => $value) {
  514.                     if ($value) {
  515.                         $orderItem $itemRepo->find($id);
  516.                         $results $invoiceService->createInvoiceFromOrderItem($orderItem);
  517.                         foreach ($results['attendees'] as $attendee) {
  518.                             $em->persist($attendee);
  519.                         }
  520.                         $em->persist($results['invoice']);
  521.                         $em->flush();
  522.                         $count++;
  523.                     }
  524.                 }
  525.                 $em->flush();
  526.             }
  527.             $this->addFlash('notice'$count . ($count === ' Rechnung' ' Rechnungen') . ' erstellt');
  528.         }
  529.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  530.     }
  531.     /**
  532.      * @Route("/{id}/invoices/merge-pdf", name="course_invoices_merge-pdf", methods="POST", requirements={"id"="\d+"})
  533.      */
  534.     public function courseMergePdf(
  535.         Request $request,
  536.         Course $course,
  537.         OrderItemRepository $repo,
  538.         PdfService $pdfService
  539.     ) {
  540.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  541.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  542.             $em $this->getDoctrine()->getManager();
  543.             $mergeIds $request->request->get('close');
  544.             if (!empty($mergeIds)) {
  545.                 $mergeInvoices = new ArrayCollection();
  546.                 foreach ($mergeIds as $id => $value) {
  547.                     if ($value) {
  548.                         $orderItem $repo->find($id);
  549.                         $order $orderItem->getOrder();
  550.                         foreach ($order->getInvoices() as $invoice) {
  551.                             if (!$mergeInvoices->contains($invoice)) {
  552.                                 $mergeInvoices->add($invoice);
  553.                             }
  554.                         }
  555.                     }
  556.                 }
  557.                 $pdf $pdfService->getMergedInvoicePdf($this->getCurrentClient(), $mergeInvoices->toArray());
  558.                 $pdf->Output('D''Rechnungen_' date('Y-m-d_H-i') . '.pdf');
  559.                 die;
  560.             } else {
  561.                 $this->addFlash('notice''Keine Rechnungen ausgewählt.');
  562.             }
  563.         }
  564.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  565.     }
  566.     /**
  567.      * @Route("/{id}/invoices/close", name="course_close_invoices", methods="POST", requirements={"id"="\d+"})
  568.      */
  569.     public function courseCloseInvoices(
  570.         Request $request,
  571.         Course $course,
  572.         InvoiceItemRepository $repo,
  573.         ConfigurationService $configService,
  574.         MailerService $mailer,
  575.         PdfService $pdfService,
  576.         EmailHistoryService $emailHistoryService
  577.     ) {
  578.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  579.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  580.             $em $this->getDoctrine()->getManager();
  581.             $closeIds $request->request->get('close');
  582.             $count 0;
  583.             if (!empty($closeIds)) {
  584.                 foreach ($closeIds as $id => $value) {
  585.                     if ($value) {
  586.                         $invoiceItem $repo->findOneBy(['orderItem' => $id]);
  587.                         $invoice $invoiceItem->getInvoice();
  588.                         if ($invoice->getStatus() == Invoice::STATUS_DRAFT) {
  589.                             $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  590.                             $sentMessage $mailer->sendInvoiceEmail(
  591.                                 $invoice,
  592.                                 'Rechnung-' $invoice->getNumber() . '.pdf',
  593.                                 $pdf->Output('S''Rechnung-' $invoice->getNumber() . '.pdf')
  594.                             );
  595.                             $outputfile $this->generateUniqueFileName() . '.pdf';
  596.                             $outputpath $this->getParameter('attachment_directory') . '/' $outputfile;
  597.                             $pdf->Output('F'$outputpath);
  598.                             $emailHistoryService->saveProtocolEntryFromInvoiceMessage(
  599.                                 $invoice,
  600.                                 $sentMessage['sender'],
  601.                                 $sentMessage['subject'],
  602.                                 $sentMessage['message'],
  603.                                 $outputfile,
  604.                                 'Rechnung-' $invoice->getNumber() . '.pdf'
  605.                             );
  606.                             if ($invoice->getStatus() != Invoice::STATUS_CLOSED) {
  607.                                 if ($invoice->isPaymentDebit()) {
  608.                                     $invoice->setStatus(Invoice::STATUS_DEBIT_PENDING);
  609.                                 } else {
  610.                                     $invoice->setStatus(Invoice::STATUS_CLOSED);
  611.                                 }
  612.                             }
  613.                             $count++;
  614.                         } else {
  615.                             // Send invoice again
  616.                             $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  617.                             $sentMessage $mailer->sendInvoiceEmail(
  618.                                 $invoice,
  619.                                 'Rechnung-' $invoice->getNumber() . '.pdf',
  620.                                 $pdf->Output('S''Rechnung-' $invoice->getNumber() . '.pdf')
  621.                             );
  622.                             $count++;
  623.                         }
  624.                         //Update the order status
  625.                         $newOrderState $invoice->getOrder()->setStatus(Order::STATUS_DONE);
  626.                         $em->persist($newOrderState);
  627.                         $em->flush();
  628.                     }
  629.                 }
  630.             }
  631.             $this->addFlash('notice'$count . ($count === ' Rechnung' ' Rechnungen') . ' versendet');
  632.         }
  633.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  634.     }
  635.     /**
  636.      * @Route("/{id}/invoices/close-sepa/{all}", name="course_close_sepa-invoices", defaults={"all"="false"},methods="POST", requirements={"id"="\d+"})
  637.      */
  638.     public function courseCloseSepaInvoices(
  639.         Request $request,
  640.         Course $course,
  641.         $all false,
  642.         OrderRepository $repo,
  643.         OrderItemRepository $itemRepo,
  644.         ConfigurationService $configService,
  645.         SepaXmlService $sepaXmlService
  646.     ) {
  647.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  648.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  649.             $em $this->getDoctrine()->getManager();
  650.             $closeIds $request->request->get('close');
  651.             $invoicesToExport = new ArrayCollection();
  652.             if ($all) {
  653.                 $orderItems $itemRepo->findByCoursePaged($course);
  654.                 foreach ($orderItems as $orderItem) {
  655.                     $order $orderItem->getOrder();
  656.                     foreach ($order->getInvoices() as $invoice) {
  657.                         if (
  658.                             $invoice->containsCourse($course) &&
  659.                             !$invoicesToExport->contains($invoice) &&
  660.                             $invoice->isPaymentDebit()
  661.                         ) {
  662.                             $invoicesToExport->add($invoice);
  663.                             $invoice->setStatus(Invoice::STATUS_CLOSED);
  664.                             if (!$order->getCustomer()->getDebitActive()) {
  665.                                 $order->getCustomer()->setDebitActive(true);
  666.                                 $invoice->setIsNewSepaMandate(true);
  667.                             }
  668.                         }
  669.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  670.                             $restsumme $invoice->getMissingSum();
  671.                             if ($restsumme != 0) {
  672.                                 $invoicePayment = new InvoicePayment();
  673.                                 $invoicePayment->setInvoice($invoice);
  674.                                 $invoicePayment->setPayedDate(new \DateTime());
  675.                                 $invoicePayment->setSum($invoice->getMissingSum());
  676.                                 $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  677.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  678.                                 $em $this->getDoctrine()->getManager();
  679.                                 $em->persist($invoicePayment);
  680.                             }
  681.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  682.                             $invoice->setExportStatus(Invoice::EXPORTED);
  683.                             $em->persist($invoice);
  684.                             $em->flush();
  685.                         }
  686.                     }
  687.                 }
  688.             } elseif (!empty($closeIds)) {
  689.                 foreach ($closeIds as $id => $value) {
  690.                     if ($value) {
  691.                         $orderItem $itemRepo->find($id);
  692.                         $order $orderItem->getOrder();
  693.                         foreach ($order->getInvoices() as $invoice) {
  694.                             if (
  695.                                 $invoice->containsCourse($course) &&
  696.                                 !$invoicesToExport->contains($invoice) &&
  697.                                 $invoice->isPaymentDebit()
  698.                             ) {
  699.                                 $invoicesToExport->add($invoice);
  700.                                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  701.                                 if (!$order->getCustomer()->getDebitActive()) {
  702.                                     $order->getCustomer()->setDebitActive(true);
  703.                                     $invoice->setIsNewSepaMandate(true);
  704.                                 }
  705.                             }
  706.                         }
  707.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  708.                             $restsumme $invoice->getMissingSum();
  709.                             if ($restsumme != 0) {
  710.                                 $invoicePayment = new InvoicePayment();
  711.                                 $invoicePayment->setInvoice($invoice);
  712.                                 $invoicePayment->setPayedDate(new \DateTime());
  713.                                 $invoicePayment->setSum($invoice->getMissingSum());
  714.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  715.                                 $em $this->getDoctrine()->getManager();
  716.                                 $em->persist($invoicePayment);
  717.                             }
  718.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  719.                             $invoice->setExportStatus(Invoice::EXPORTED);
  720.                             $em->persist($invoice);
  721.                             $em->flush();
  722.                         }
  723.                     }
  724.                 }
  725.             } else {
  726.                 $this->addFlash('warning''Es wurden keine Rechnungen zum Export ausgewählt.');
  727.                 return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  728.             }
  729.             // Check invoices for past due dates
  730.             foreach ($invoicesToExport as $invoice) {
  731.                 if (new \DateTime() > $invoice->getDueDate()) {
  732.                     $this->addFlash('warning''Mindestens eine Rechnung enthält ein Zahlungsziel in der Vergangenheit.');
  733.                     // return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  734.                 }
  735.             }
  736.             if (count($invoicesToExport) > 0) {
  737.                 $config $configService->getSepaXmlConfigByClient($this->getCurrentClient());
  738.                 try {
  739.                     $xml $sepaXmlService->getSepaXmlMultiple($this->getCurrentClient(), $config$invoicesToExport);
  740.                 } catch (ServiceException $e) {
  741.                     $this->addFlash('error'$e->getMessage());
  742.                     return $this->redirectToRoute('invoice_index');
  743.                 }
  744.                 $em->flush();
  745.                 $response = new Response($xml);
  746.                 $response->headers->set('Content-Type''text/xml');
  747.                 $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  748.                 return $response;
  749.             }
  750.             $this->addFlash('error''Mindestens eine Rechnung enthält Fehler.');
  751.             return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  752.         }
  753.         $this->addFlash('error''Der Sicherheits-Token ist ungültig. Bitte versuchen Sie es noch einmal.');
  754.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  755.     }
  756.     /**
  757.      * @Route("/{id}/invoices/close-sepa/", name="course_close_sepa-invoice_selected", methods="POST", requirements={"id"="\d+"})
  758.      */
  759.     public function courseCloseSepaInvoiceSelected(
  760.         Request $request,
  761.         Course $course,
  762.         OrderItemRepository $itemRepo,
  763.         ConfigurationService $configService,
  764.         SepaXmlService $sepaXmlService
  765.     ) {
  766.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  767.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  768.             $em $this->getDoctrine()->getManager();
  769.             $closeIds $request->request->get('close');
  770.             $invoicesToExport = new ArrayCollection();
  771.         if (!empty($closeIds)) {
  772.                 foreach ($closeIds as $id => $value) {
  773.                     if ($value) {
  774.                         $orderItem $itemRepo->find($id);
  775.                         $order $orderItem->getOrder();
  776.                         foreach ($order->getInvoices() as $invoice) {
  777.                             if (
  778.                                 $invoice->containsCourse($course) &&
  779.                                 !$invoicesToExport->contains($invoice) &&
  780.                                 $invoice->isPaymentDebit()
  781.                             ) {
  782.                                 $invoicesToExport->add($invoice);
  783.                                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  784.                                 if (!$order->getCustomer()->getDebitActive()) {
  785.                                     $order->getCustomer()->setDebitActive(true);
  786.                                     $invoice->setIsNewSepaMandate(true);
  787.                                 }
  788.                             }
  789.                         }
  790.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  791.                             $restsumme $invoice->getMissingSum();
  792.                             if ($restsumme != 0) {
  793.                                 $invoicePayment = new InvoicePayment();
  794.                                 $invoicePayment->setInvoice($invoice);
  795.                                 $invoicePayment->setPayedDate(new \DateTime());
  796.                                 $invoicePayment->setSum($invoice->getMissingSum());
  797.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  798.                                 $em $this->getDoctrine()->getManager();
  799.                                 $em->persist($invoicePayment);
  800.                             }
  801.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  802.                             $invoice->setExportStatus(Invoice::EXPORTED);
  803.                             $em->persist($invoice);
  804.                             $em->flush();
  805.                         }
  806.                     }
  807.                 }
  808.             } else {
  809.                 $this->addFlash('warning''Es wurden keine Rechnungen zum Export ausgewählt.');
  810.                 return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  811.             }
  812.             // Check invoices for past due dates
  813.             foreach ($invoicesToExport as $invoice) {
  814.                 if (new \DateTime() > $invoice->getDueDate()) {
  815.                    
  816.                     $this->addFlash('warning''Mindestens eine Rechnung enthält ein Zahlungsziel in der Vergangenheit.');
  817.                     // return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  818.                 }
  819.             }
  820.             if (count($invoicesToExport) > 0) {
  821.                 $config $configService->getSepaXmlConfigByClient($this->getCurrentClient());
  822.                 try {
  823.                     $xml $sepaXmlService->getSepaXmlMultiple($this->getCurrentClient(), $config$invoicesToExport);
  824.                 } catch (ServiceException $e) {
  825.                     $this->addFlash('error'$e->getMessage());
  826.                     return $this->redirectToRoute('invoice_index');
  827.                 }
  828.                 $em->flush();
  829.                 $response = new Response($xml);
  830.                 $response->headers->set('Content-Type''text/xml');
  831.                 $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  832.                 return $response;
  833.             }
  834.             $this->addFlash('error''Mindestens eine Rechnung enthält Fehler.');
  835.             return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  836.         }
  837.         $this->addFlash('error''Der Sicherheits-Token ist ungültig. Bitte versuchen Sie es noch einmal.');
  838.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  839.     }
  840.     /**
  841.      * @Route("/{id}/participants", name="course_participants", methods="GET", requirements={"id"="\d+"})
  842.      */
  843.     public function courseParticipants(
  844.         Request $request,
  845.         Course $course,
  846.         OrderItemRepository $repo,
  847.         OrderService $orderService,
  848.         TagsPersonRepository  $tagsPersonRepository,
  849.     ) {
  850.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  851.         $orderItems $repo->findByCoursePaged($course);
  852.         /**
  853.          * The display logic of subscription courses is different, as there only one order exists per
  854.          * customer/participant, but they should appear in every following course occurrence until they cancel.
  855.          */
  856.         // if ($course->getCourseNature() === 'CourseSubscription') {
  857.         //     return $this->render('course/participants-subscription.html.twig', [
  858.         //         'course' => $course,
  859.         //         'orderItems' => $orderItems->getIterator(),
  860.         //     ]);
  861.         // } else {
  862.         $archive = !empty($request->get('archive'));
  863.         if ($course->getCourseNature() === 'CourseSubscription') {
  864.             foreach ($orderItems as $orderItem) {
  865.                 foreach ($orderItem->getParticipants() as $participant) {
  866.                     $participant->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem$participant->getId());
  867.                     $participant->cancelDate $orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant);
  868.                 }
  869.             }
  870.         }
  871.         return $this->render('course/participants.html.twig', [
  872.             'tagsPerson' => $tagsPersonRepository->findAll(),
  873.             'env' => $_ENV,
  874.             'course' => $course,
  875.             'orderItems' => $orderItems->getIterator(),
  876.             'showCertificatesLink' => !empty($_ENV['CERTIFICATES_ENABLED']),
  877.             'archive' => $archive,
  878.         ]);
  879.         // }
  880.     }
  881.     /**
  882.      * @Route("/{id}/participants-pdf/{page}/{orderby}/{order}", name="course_participants_pdf", methods="GET", requirements={"id"="\d+"})
  883.      * @IsGranted("ROLE_SPEAKER")
  884.      */
  885.     public function courseParticipantsPdf(
  886.         Request $request,
  887.         CourseOccurrence $courseOccurrence,
  888.         OrderItemRepository $repo,
  889.         PdfService $pdfService,
  890.         OrderService $orderService,
  891.         $page 1,
  892.         $orderby 'customerLastname',
  893.         $order 'asc'
  894.     ) {
  895.         //    $this->denyAccessUnlessGranted('client_allowed', $courseOccurrence);
  896.         $this->denyAccessUnlessGranted('ROLE_SPEAKER'$courseOccurrence);
  897.         $orderItems $repo->findByCourseOccurrence($courseOccurrence$orderby$order);
  898.         if ($courseOccurrence->getCourse()->getCourseNature() === 'CourseSubscription') {
  899.             foreach ($orderItems as $orderItem) {
  900.                 foreach ($orderItem->getParticipants() as $participant) {
  901.                     $participant->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem$participant->getId());
  902.                 }
  903.             }
  904.         }
  905.         $pdf $pdfService->getParticipantsPdf($this->getCurrentClient(), $courseOccurrence$orderItems);
  906.         $pdf->Output('D''Teilnehmerliste-' $courseOccurrence->getStart()->format('Y-m-d') . '.pdf');
  907.         exit();
  908.     }
  909.     /**
  910.      * @Route("/participant/{id}/certificateemail", name="course_participants_certificate_email", methods="GET", requirements={"id"="\d+","downlaod"="\d+"})
  911.      */
  912.     public function courseParticipantsCertificateEmail(
  913.         Request $request,
  914.         ConfigurationService $configService,
  915.         \App\Entity\OrderItemPerson $orderItemPerson,
  916.         TextblocksRepository $textblocks,
  917.         ParameterBagInterface $params,
  918.         CourseDataRepository $courseDataRepository,
  919.         MailerService $mailer,
  920.         \Doctrine\DBAL\Driver\Connection $connection,
  921.         EmailHistoryService $emailHistoryService
  922.     ): Response {
  923.         $download $_GET['download'];
  924.         $viewTemplate $_ENV['CERTIFICATES_TEMPLATE'] ?? 'Default';
  925.         $viewFolder '/data/static/certificates/';
  926.         $viewFile $viewTemplate '/Certificate.html.twig';
  927.         if (file_exists($params->get('kernel.project_dir') . $viewFolder dirname($viewFile) . '/data.xml')) {
  928.             $xml simplexml_load_file($params->get('kernel.project_dir') . $viewFolder dirname($viewFile) . '/data.xml''SimpleXMLElement'LIBXML_NOCDATA);
  929.             $json json_encode($xml);
  930.             $data json_decode($jsontrue);
  931.         }
  932.         try {
  933.             $course $orderItemPerson->getOrderItem()->getCourseOccurrence()->getCourse();
  934.             $person $orderItemPerson->getPerson();
  935.             $customer $orderItemPerson->getOrderItem()->getOrder()->getCustomer();
  936.             $courseFields $courseDataRepository->findBy([
  937.                 'course' => $course,
  938.                 'client' => $this->getCurrentClient()
  939.             ]);
  940.             //proof if an certificate isset
  941.             $certificateIsset false;
  942.             foreach ($courseFields as $field) {
  943.                 if (
  944.                     $field->getCourseField()->getCertificate() &&
  945.                     !empty($field->getValueText())
  946.                 ) {
  947.                     $certificateIsset true;
  948.                     break;
  949.                 }
  950.             }
  951.             $response $this->render('course/certificates/' $viewTemplate '/Certificate.html.twig', [
  952.                 'data' => $data ?? [],
  953.                 'folder' => '..' $viewFolder dirname($viewFile) . '/',
  954.                 'person' => $person,
  955.                 'course' => $course,
  956.                 'courseFields' => $courseFields,
  957.                 'certificateIsset' => $certificateIsset,
  958.                 'occurence' => $orderItemPerson->getOrderItem()->getCourseOccurrence(),
  959.             ]);
  960.         } catch (\Twig\Error\LoaderError $exception) {
  961.             $this->addFlash('error''Das Zertifikat konnte nicht erstellt werden (Ordner: ' $viewFolder ').');
  962.             return $this->redirectToRoute('course_participants', ['id' => $orderItemPerson->getOrderItem()->getCourseOccurrence()->getCourse()->getId()]);
  963.         } catch (\InvalidArgumentException $exception) {
  964.             $this->addFlash('error''Das Zertifikat konnte nicht erstellt werden (Template: ' $viewFile ').');
  965.             return $this->redirectToRoute('course_participants', ['id' => $orderItemPerson->getOrderItem()->getCourseOccurrence()->getCourse()->getId()]);
  966.         }
  967.         $source $response->getContent();
  968.         // Generate filename
  969.         $filename $course->getNumber() . '-' $person->getLastname() . '-' $person->getFirstname();
  970.         $filename mb_strtolower($filename);
  971.         $tr = [
  972.             'ä' => 'ae',
  973.             'ü' => 'ue',
  974.             'ö' => 'oe',
  975.             'ß' => 'ss',
  976.         ];
  977.         $filename strtr($filename$tr);
  978.         $filename preg_replace('#\s#''-'$filename);
  979.         $filename preg_replace('#[^a-z0-9\-]#'''$filename);
  980.         $filename preg_replace('#[\-]{2,}#i''-'$filename);
  981.         $filename .= '.pdf';
  982.         // Generate pdf
  983.         $html2pdf = new \Spipu\Html2Pdf\Html2Pdf('P''A4''de'true'UTF-8', [251000]);
  984.         $html2pdf->setDefaultFont('DejaVuSans');
  985.         $html2pdf->writeHTML($source);
  986.         if ($download == 'ja') {
  987.             $html2pdf->output($filename'D');
  988.         }
  989.         $outputpath $this->getParameter('attachment_directory') . '/' $filename;
  990.         if ($download == 'nein') {
  991.             $html2pdf->output($outputpath'F');
  992.         }
  993.         $client $this->getCurrentClient();
  994.         $sender $client->getEmail();
  995.         $recipient $person->getContactEmail() ? $person->getContactEmail() :  $orderItemPerson->getEmail();
  996.         // Fetch subject und message from textblocks
  997.         $sql 'SELECT * FROM textblocks WHERE position = "certificate" ';
  998.         $result $connection->fetchAll($sql);
  999.         $subject 'Ihr Zertifikat wurde erstellt';
  1000.         $message 'Lieber Teilnehmer<p>Für Ihren Kurs wurde das Zertifikat erstellt.</p><p>Ihr Team';
  1001.         $historyTitle 'Zertifikat erstellt';
  1002.         if ($download == 'nein') {
  1003.             foreach ($result as $value) {
  1004.                 if ($value['position'] = 'cetrificate') {
  1005.                     $subject $value['subject'];
  1006.                     $message $value['message'];
  1007.                 }
  1008.             }
  1009.             $mailer->sendCertificateMessage(
  1010.                 $client,
  1011.                 $sender,
  1012.                 $subject ' ' $course->getTitle(),
  1013.                 $message '<p>Anhang: ' $filename,
  1014.                 $recipient,
  1015.                 $html2pdf->output($filename'S'),
  1016.                 $filename
  1017.             );
  1018.         }
  1019.         //$client, $recipient, $sender, $subject, $message, $filename
  1020.         $emailHistoryService->saveProtocolEntriesFromEmailCertificate(
  1021.             $this->getCurrentClient(),
  1022.             $recipient,
  1023.             $sender,
  1024.             $subject  ' ' $course->getTitle(),
  1025.             $message,
  1026.             $filename,
  1027.             $historyTitle,
  1028.             $customer,
  1029.             $download
  1030.         );
  1031.         if ($download == 'nein') {
  1032.             $this->addFlash('notice''Das Zertifikat wurde an ' $recipient ' versendet. ');
  1033.         }
  1034.         if ($download == 'ja') {
  1035.             $this->addFlash('notice''Das Zertifikat wurde erstellt. ');
  1036.         }
  1037.         return $this->redirectToRoute('course_participants', ['id' => $course->getId()]);
  1038.     }
  1039.     /**
  1040.      * @Route("/{id}/reservations", name="course_reservations", methods="GET", requirements={"id"="\d+"})
  1041.      */
  1042.     public function courseReservations(
  1043.         Request $request,
  1044.         Course $course,
  1045.         WaitItemRepository $repo,
  1046.         TagsPersonRepository  $tagsPersonRepository,
  1047.     ) {
  1048.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  1049.         $waitItems $repo->findByCoursePaged($course);
  1050.         return $this->render('course/reservations.html.twig', [
  1051.             'course' => $course,
  1052.             'waitItems' => $waitItems->getIterator(),
  1053.             'tagsPerson' => $tagsPersonRepository->findAll(),
  1054.         ]);
  1055.     }
  1056.     /**
  1057.      * @Route("/{id}/reservations/move", name="course_reservations_move", methods="POST", requirements={"id"="\d+"})
  1058.      */
  1059.     public function moveCourseReservations(
  1060.         Request $request,
  1061.         Course $course,
  1062.         WaitItemRepository $repo
  1063.     ): Response {
  1064.         $this->denyAccessUnlessGranted('ROLE_ADMIN'$course);
  1065.         $em $this->getDoctrine()->getManager();
  1066.         $moveIds $request->request->get('item');
  1067.         foreach ($moveIds as $id => $value) {
  1068.             if ($value) {
  1069.                 $waitItem $repo->find($value);
  1070.                 $orderItem OrderItem::createFromWaitItem($waitItem);
  1071.                 $participants $waitItem->getParticipants();
  1072.                 foreach ($participants as $participant) {
  1073.                     if ($participant->getPerson()->getId() === $id) {
  1074.                         $participant->setWaitItem(null);
  1075.                         $participant->setOrderItem($orderItem);
  1076.                         $orderItem->setQuantity($orderItem->getQuantity() + 1);
  1077.                         $waitItem->setQuantity($waitItem->getQuantity() - 1);
  1078.                         break;
  1079.                     }
  1080.                 }
  1081.                 $waitItem->getCourseOccurrence()->bookSlots($orderItem->getQuantity());
  1082.                 $order $waitItem->getOrder();
  1083.                 $order->addOrderItem($orderItem);
  1084.                 if ($waitItem->getQuantity() === 0) {
  1085.                     $order->removeWaitItem($waitItem);
  1086.                 }
  1087.                 $em->persist($order);
  1088.             }
  1089.         }
  1090.         $this->addFlash('notice'count($moveIds) . (count($moveIds) > ' Wartelistenplätze verschoben' ' Wartelistenplatz verschoben'));
  1091.         $em->flush();
  1092.         return $this->redirectToRoute('course_reservations',  ['id' => $course->getId()]);
  1093.     }
  1094.     private function generateUniqueFileName()
  1095.     {
  1096.         return md5(uniqid());
  1097.     }
  1098.     private function createDescription($field$option)
  1099.     {
  1100.         switch ($option) {
  1101.             case 'course':
  1102.                 if (!empty($field['certificate'])) {
  1103.                     $field['name'] = $this->generateHTMLForDescription(
  1104.                         $field['name'],
  1105.                         'für den Kurs und das Zertifikat'
  1106.                     );
  1107.                 } else {
  1108.                     $field['name'] = $this->generateHTMLForDescription(
  1109.                         $field['name'],
  1110.                         'für den Kurs'
  1111.                     );
  1112.                 }
  1113.                 break;
  1114.             case 'certificate':
  1115.                 $field['name'] = $this->generateHTMLForDescription(
  1116.                     $field['name'],
  1117.                     'für das Zertifikat'
  1118.                 );
  1119.                 break;
  1120.             default:
  1121.                 break;
  1122.         }
  1123.         return $field;
  1124.     }
  1125.     private function generateHTMLForDescription($name$text)
  1126.     {
  1127.         return '<strong>' $name '</strong>' .  '<span style="font-size: 0.7rem"> (' $text ')</span>';
  1128.     }
  1129. }