src/Controller/CourseController.php line 784

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Course;
  4. use App\Entity\Order;
  5. use App\Entity\CourseData;
  6. use App\Entity\Invoice;
  7. use App\Form\CourseType;
  8. use App\Entity\OrderItemPerson;
  9. use App\Repository\CourseFieldRepository;
  10. use App\Repository\CourseDataRepository;
  11. use App\Service\PdfService;
  12. use App\Form\CourseImagesType;
  13. use App\Service\MailerService;
  14. use App\Service\InvoiceService;
  15. use App\Service\SepaXmlService;
  16. use App\Entity\InvoicePayment;
  17. use App\Entity\CourseOccurrence;
  18. use App\Repository\CourseOccurrenceTimeRepository;
  19. use App\Repository\TagsPersonRepository;
  20. use App\Repository\PersonRepository;
  21. use App\Repository\SpeakerRepository;
  22. use App\Repository\PresenceRepository;
  23. use App\Entity\OrderItem;
  24. use App\Service\CertificateService;
  25. use App\Repository\OrderRepository;
  26. use App\Repository\CourseRepository;
  27. use App\Service\EmailHistoryService;
  28. use App\Service\ConfigurationService;
  29. use App\Repository\CartItemRepository;
  30. use Doctrine\Persistence\ManagerRegistry;
  31. use App\Entity\Presence;
  32. use Doctrine\ORM\EntityManagerInterface;
  33. use App\Repository\TextblocksRepository;
  34. use App\Repository\WaitItemRepository;
  35. use App\Repository\OrderItemRepository;
  36. use App\Service\Exception\ServiceException;
  37. use App\Repository\CourseOccurrenceRepository;
  38. use App\Repository\InvoiceItemRepository;
  39. use App\Service\OrderService;
  40. use Symfony\Component\HttpFoundation\Response;
  41. use Symfony\Component\HttpFoundation\JsonResponse;
  42. use Symfony\Component\HttpFoundation\Request;
  43. use Symfony\Component\Routing\Annotation\Route;
  44. use Doctrine\Common\Collections\ArrayCollection;
  45. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  46. use Menke\UserBundle\Controller\AbstractClientableController;
  47. /**
  48.  * @Route("/course")
  49.  * @IsGranted("ROLE_SPEAKER")
  50.  */
  51. class CourseController extends AbstractClientableController
  52. {
  53.     private $managerRegistry;
  54.     private $certificateService;
  55.     public function __construct(ManagerRegistry $managerRegistryCertificateService $certificateService)
  56.     {
  57.         $this->managerRegistry $managerRegistry->getManager();
  58.         $this->certificateService $certificateService;
  59.     }
  60.     const LISTING_LIMIT 20;
  61.     /**
  62.      *
  63.      */
  64.     private function getListingLimit(): int
  65.     {
  66.         return !empty($_ENV['COURSES_LISTINGLIMIT']) ? (int) $_ENV['COURSES_LISTINGLIMIT'] : 4;
  67.     }
  68.     /**
  69.      * @Route("/", name="course_index", methods="GET")
  70.      */
  71.     public function index(
  72.         Request $request,
  73.         \App\Service\UiService $uiService,
  74.         CourseRepository $courseRepository,
  75.         EntityManagerInterface $manager,
  76.         SpeakerRepository $speakerRepository
  77.        
  78.     ): Response {
  79.       //  $this->denyAccessUnlessGranted('ROLE_MANAGER');
  80.         $order $uiService->getSortOrder('course-index-listing');
  81.         $archive = !empty($request->get('archive'));
  82.         ///////////////////////////////////////////////////////////
  83. $user $this->getCurrentUser();
  84. $speaker $speakerRepository->getByUser($user);
  85. /*
  86. if ($speaker == null) {
  87.     $this->addFlash('error', 'Sie sind kein Speaker');
  88.     return $this->redirectToRoute('dashboard');
  89. }else{
  90. $this->addFlash('notice', 'Speaker ID: ' . $speaker->getId().' Person ID'.$user->getId());
  91. }*/
  92.         $courses $courseRepository->getCoursesByClientPaged(
  93.             $this->getCurrentClient(),
  94.             $this->getListingLimit(),
  95.             $order['orderDirection'] ?? 'ASC',
  96.             $order['orderBy'] ?? 'title',
  97.             1,
  98.             $archive,
  99.             $speaker,
  100.         );
  101.         // die Anzahl der Kurse mit den gebuchten überprüfen und die bookedSlots bei den CourseOccurreces aktualisieren
  102.         $this->manager $manager;
  103.         foreach ($courses as $course
  104.         {
  105.             foreach ($course->getOccurrences() as $occurrence
  106.                         {
  107.                             $occurrence->setBookedSlots($occurrence->getBookedSlots());
  108.                             $this->manager->persist($occurrence);
  109.                         }
  110.          }
  111.          $this->manager->flush();
  112.          if ($speaker == null) {
  113.             $render 'course/index.html.twig';
  114.         }else{
  115.             $render 'course/index_speaker.html.twig';
  116.         }
  117.          ///////////////////////////////////////////
  118.         return $this->render($render, [
  119.             'uiService' => $uiService,
  120.             'courses' =>  $courses,
  121.             'total' => $courses->count(),
  122.             'pages' => ceil($courses->count() / $this->getListingLimit()),
  123.             'page' => 1,
  124.             'archive' => $archive,
  125.             'env' => $_ENV,
  126.             'user' => $user,
  127.         ]);
  128.     }
  129.     /**
  130.      * @Route("/{page}/{orderby}/{order}", name="course_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
  131.      */
  132.     public function indexListing(
  133.         Request $request,
  134.         CourseRepository $courseRepository,
  135.         \App\Service\UiService $uiService,
  136.         $page,
  137.         $orderby,
  138.         $order
  139.     ): Response {
  140.         $uiService->storeSortOrder('course-index-listing'$orderby$order);
  141.         $archive = !empty($request->get('archive'));
  142.         $courses $courseRepository->getCoursesByClientPaged($this->getCurrentClient(), $this->getListingLimit(), $order$orderby$page$archive);
  143.         return $this->render('course/_index_listing.html.twig', [
  144.             'courses' => $courses,
  145.             'total' => $courses->count(),
  146.             'pages' => ceil($courses->count() / $this->getListingLimit()),
  147.             'page' => $page,
  148.             'archive' => $archive,
  149.             'env' => $_ENV,
  150.         ]);
  151.     }
  152.     /**
  153.      * @Route("/new", name="course_new", methods="GET|POST")
  154.      */
  155.     public function new(Request $requestConfigurationService $configService): Response
  156.     {
  157.         $course = new Course();
  158.         if (!empty($courseNature $request->get('courseNature'))) {
  159.             $course->setCourseNature($courseNature);
  160.         }
  161.         $form $this->createForm(CourseType::class, $course, [
  162.             'client' => $this->getCurrentClient(),
  163.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  164.         ]);
  165.         $form->handleRequest($request);
  166.         if ($form->isSubmitted() && $form->isValid()) {
  167.             $course->setClient($this->getCurrentClient());
  168.             $course->setNumber($configService->getNewCourseNumberByClient($this->getCurrentClient()));
  169.             foreach ($course->getTexts() as $key => $text) {
  170.                 $text->setCreated(new \DateTime());
  171.                 if (empty($text->getOrderId())) {
  172.                     $text->setOrderId($key 1000);
  173.                 }
  174.             }
  175.             $em $this->getDoctrine()->getManager();
  176.             $course->setCreated(new \DateTime());
  177.             $em->persist($course);
  178.             $em->flush();
  179.             $this->addFlash('success''Kurs angelegt');
  180.             return $this->redirectToRoute('course-occurrence_new', ['courseId' => $course->getId()]);
  181.         }
  182.         return $this->render('course/new.html.twig', [
  183.             'course' => $course,
  184.             'fields' => null,
  185.             'form' => $form->createView(),
  186.         ]);
  187.     }
  188.     /**
  189.      * @Route("/{id}/edit", name="course_edit", methods="GET|POST", requirements={"id"="\d+"})
  190.      */
  191.     public function edit(
  192.         Request $request,
  193.         Course $course,
  194.         ConfigurationService $configService,
  195.         CourseFieldRepository $courseFieldRepository,
  196.         CourseDataRepository $courseDataRepository
  197.     ): Response {
  198.       //  $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  199.         $courseTexts = new ArrayCollection();
  200.         foreach ($course->getTexts() as $text) {
  201.             $courseTexts->add($text);
  202.         }
  203.         $form $this->createForm(CourseType::class, $course, [
  204.             'client' => $this->getCurrentClient(),
  205.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  206.         ]);
  207.         $form->handleRequest($request);
  208.         if ($form->isSubmitted() && $form->isValid()) {
  209.             $manager $this->getDoctrine()->getManager();
  210.             foreach ($courseTexts as $text) {
  211.                 if (false === $course->getTexts()->contains($text)) {
  212.                     $text->setCourse(null);
  213.                     $manager->remove($text);
  214.                 }
  215.             }
  216.             foreach ($course->getTexts() as $key => $text) {
  217.                 if (empty($text->getOrderId())) {
  218.                     $text->setCreated(new \DateTime());
  219.                     $text->setOrderId($key 1000);
  220.                 }
  221.                 $text->setModified(new \DateTime());
  222.             }
  223.             $fields $request->request->get('fields');
  224.             if (!is_null($fields)) {
  225.                 foreach ($fields as $fieldId => $value) {
  226.                     $field $courseFieldRepository->find($fieldId);
  227.                     $data $courseDataRepository->findBy([
  228.                         'course' => $course,
  229.                         'field' => $field,
  230.                     ]);
  231.                     if (count($data) == 0) {
  232.                         $data = new CourseData();
  233.                         $data->setClient($this->getCurrentClient());
  234.                         $data->setCourse($course);
  235.                         $data->setField($field);
  236.                         $data->setCreated(new \datetime());
  237.                         $manager->persist($data);
  238.                     } else {
  239.                         $data $data[0];
  240.                     }
  241.                     $data->setValueText($value);
  242.                     $data->setModified(new \datetime());
  243.                 }
  244.             } else {
  245.                 $fields = [];
  246.             }
  247.             $course->setModified(new \datetime());
  248.             $manager->flush();
  249.             $this->addFlash('notice''Kurs gespeichert');
  250.             return $this->redirectToRoute('course_edit', ['id' => $course->getId()]);
  251.         }
  252.         // Fetch course fields
  253.         $sql 'SELECT
  254.             f.*,
  255.             d.value_text,
  256.             d.value_integer,
  257.             d.value_date
  258.         FROM
  259.             course_field f
  260.         LEFT JOIN
  261.             course_data d
  262.         ON 
  263.             d.field_id = f.id AND
  264.             d.course_id = ' $course->getId();
  265.         $em $this->getDoctrine()->getManager();
  266.         $stmt $em->getConnection()->prepare($sql);
  267.         $stmt->execute();
  268.         $result $stmt->fetchAll();
  269.         $fields = [];
  270.         $isset false;
  271.         foreach ($result as $field) {
  272.             $isset false;
  273.             if (!empty($field['category'])) {
  274.                 if (!$course->getCategory()) {
  275.                     continue;
  276.                 }
  277.                 if (!in_array($course->getCategory()->getId(), json_decode($field['category'], true))) {
  278.                     continue;
  279.                 } else {
  280.                     $field $this->createDescription($field'course');
  281.                     $isset true;
  282.                 }
  283.             }
  284.             if (!empty($field['course_type'])) {
  285.                 if (!$course->getType()) {
  286.                     continue;
  287.                 }
  288.                 if (!in_array($course->getType()->getId(), json_decode($field['course_type'], true))) {
  289.                     continue;
  290.                 } else {
  291.                     if (!$isset) {
  292.                         $field $this->createDescription($field'course');
  293.                         $isset true;
  294.                     }
  295.                 }
  296.             }
  297.             if (empty($field['category']) && empty($field['course_type']) && !empty($field['certificate'])) {
  298.                 if (!$isset$field $this->createDescription($field'certificate');
  299.             }
  300.             if (
  301.                 !empty($field['category']) ||
  302.                 !empty($field['course_type']) ||
  303.                 $field['certificate']
  304.             ) {
  305.                 $fields[] = $field;
  306.             }
  307.         }
  308.         return $this->render('course/edit.html.twig', [
  309.             'course' => $course,
  310.             'form' => $form->createView(),
  311.             'fields' => $fields,
  312.             'env' => $_ENV,
  313.         ]);
  314.     }
  315.     /**
  316.      * @Route("/{id}", name="course_delete", methods="DELETE", requirements={"id"="\d+"})
  317.      */
  318.     public function delete(Request $requestCourse $course): Response
  319.     {
  320.        //  $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  321.         if ($this->isCsrfTokenValid('delete' $course->getId(), $request->request->get('_token'))) {
  322.             $em $this->getDoctrine()->getManager();
  323.             $em->remove($course);
  324.             try {
  325.                 $em->flush();
  326.             } 
  327.             catch (\Exception $e
  328.             {
  329.                 $errorMessage $e->getMessage();
  330.                 if (str_contains($errorMessage'Integrity constraint violation'))
  331.                 {
  332.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.');
  333.        //         $this->addFlash('error', $errorMessage); 
  334.                 
  335.                 else 
  336.                 {
  337.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.'); 
  338.                 }
  339.                return $this->redirectToRoute('course_index');
  340.             }
  341.         $this->addFlash('notice''Kurs gelöscht');
  342.         }
  343.         return $this->redirectToRoute('course_index');
  344.     }
  345.     /**
  346.      * @Route("/multiple", name="course_delete-multiple", methods="DELETE")
  347.      */
  348.     public function deleteMultiple(
  349.         Request $request,
  350.         CourseRepository $courseRepo,
  351.         CartItemRepository $cartItemRepo,
  352.         WaitItemRepository $waitItemRepo,
  353.         OrderItemRepository $orderItemRepo
  354.     ): Response {
  355.         if ($this->isCsrfTokenValid('delete_courses'$request->request->get('_token'))) {
  356.             $em $this->getDoctrine()->getManager();
  357.             $deleteIds $request->request->get('delete');
  358.             foreach ($deleteIds as $id => $value) {
  359.                 if ($value) {
  360.                     $course $courseRepo->find($id);
  361.                     $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  362.                     $waitItems $waitItemRepo->findBy(['course' => $course]);
  363.                     foreach ($waitItems as $waitItem) {
  364.                         $em->remove($waitItem);
  365.                     }
  366.                     $cartItems $cartItemRepo->findBy(['course' => $course]);
  367.                     foreach ($cartItems as $cartItem) {
  368.                         $em->remove($cartItem);
  369.                     }
  370.                     $orderItems $orderItemRepo->findBy(['course' => $course]);
  371.                     foreach ($orderItems as $orderItem) {
  372.                         $orderItem->setCourseOccurrence(null);
  373.                     }
  374.                     $em->remove($course);
  375.                 }
  376.             }
  377.             try {
  378.                 $em->flush();
  379.             } catch (\Exception $e) {
  380.                 $errorMessage $e->getMessage();
  381.                 if (str_contains($errorMessage'Integrity constraint violation')){
  382.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.');
  383.        //         $this->addFlash('error', $errorMessage); 
  384.                 } else {
  385.                 $this->addFlash('error''Der Kurs kann nicht gelöscht werden, weil er an anderer Stelle gebraucht wird.'); 
  386.                 }
  387.                return $this->redirectToRoute('course_index');
  388.                
  389.             }
  390.             
  391.             $this->addFlash('notice'count($deleteIds) > 'Kurse gelöscht' 'Kurs gelöscht');
  392.         }
  393.         return $this->redirectToRoute('course_index');
  394.     }
  395.     /**
  396.      * @Route("/{id}/occurrences", name="course_occurrences", methods="GET", requirements={"id"="\d+"})
  397.      */
  398.     public function courseOccurrences(
  399.         Request $request,
  400.         Course $course,
  401.         CourseOccurrenceRepository $repo,
  402.         \App\Service\UiService $uiService
  403.     ): Response {
  404.      //   $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  405.         $order $uiService->getSortOrder('course-occurrences-listing');
  406.         $archive = !empty($request->get('archive'));
  407.         $occurrences $repo->findByCoursePaged(
  408.             $course,
  409.             self::LISTING_LIMIT,
  410.             $order['orderDirection'] ?? 'ASC',
  411.             $order['orderBy'] ?? 'title'
  412.         );
  413.         return $this->render('course/occurrences.html.twig', [
  414.             'uiService' => $uiService,
  415.             'course' => $course,
  416.             'occurrences' => $occurrences->getIterator(),
  417.             'total' => $occurrences->count(),
  418.             'pages' => ceil($occurrences->count() / self::LISTING_LIMIT),
  419.             'page' => 1,
  420.             'env' => $_ENV,
  421.             'archive' => $archive,
  422.         ]);
  423.     }
  424.     /**
  425.      * @Route("/{id}/occurrences/{page}/{orderby}/{order}/{search}", name="course_occurrences_listing", methods="GET", defaults={"search"="", "order"="desc", "orderby"="start"}, requirements={"id"="\d+"})
  426.      */
  427.     public function courseOccurrencesListing(
  428.         Request $request,
  429.         Course $course,
  430.         $page,
  431.         $orderby,
  432.         $order,
  433.         $search,
  434.         CourseOccurrenceRepository $repo,
  435.         \App\Service\UiService $uiService
  436.     ): Response {
  437.     //    $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  438.         $uiService->storeSortOrder('course-occurrences-listing'$orderby$order);
  439.         $occurrences $repo->findByCoursePaged($courseself::LISTING_LIMIT$order$orderby$page$search);
  440.         return $this->render('course/tabs/_occurrences_listing.html.twig', [
  441.             'course' => $course,
  442.             'occurrences' => $occurrences->getIterator(),
  443.             'total' => $occurrences->count(),
  444.             'pages' => ceil($occurrences->count() / self::LISTING_LIMIT),
  445.             'page' => $page,
  446.             'env' => $_ENV,
  447.         ]);
  448.     }
  449.     /**
  450.      * @Route("/{id}/images", name="course_images", methods="GET|POST", requirements={"id"="\d+"})
  451.      */
  452.     public function courseImages(Request $requestCourse $course)
  453.     {
  454.     //    $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  455.         $courseImages = new ArrayCollection();
  456.         foreach ($course->getImages() as $image) {
  457.             $courseImages->add($image);
  458.         }
  459.         $form $this->createForm(CourseImagesType::class, $course);
  460.         $form->handleRequest($request);
  461.         if ($form->isSubmitted() && $form->isValid()) {
  462.             $manager $this->getDoctrine()->getManager();
  463.             foreach ($courseImages as $image) {
  464.                 $image->setCreated(new \Datetime());
  465.                 if (false === $course->getImages()->contains($image)) {
  466.                     $image->setCourse(null);
  467.                     $manager->remove($image);
  468.                 }
  469.             }
  470.             foreach ($course->getImages() as $key => $image) {
  471.                 // Setze das `created`-Datum, falls es nicht gesetzt wurde
  472.                 if (null === $image->getCreated()) {
  473.                     $image->setCreated(new \DateTime());
  474.                 }
  475.         
  476.                 // Setze die Reihenfolge, falls `orderId` leer ist
  477.                 if (empty($image->getOrderId())) {
  478.                     $image->setOrderId($key 1000);
  479.                 }
  480.             }
  481.            
  482.             $manager->flush();
  483.             $this->addFlash('notice''Kursbilder gespeichert');
  484.             return $this->redirectToRoute('course_images', ['id' => $course->getId()]);
  485.         }
  486.         return $this->render('course/images.html.twig', [
  487.             'course' => $course,
  488.             'form' => $form->createView(),
  489.             'env' => $_ENV,
  490.         ]);
  491.     }
  492.     /**
  493.      * @Route("/{id}/invoices", name="course_invoices", methods="GET", requirements={"id"="\d+"})
  494.      */
  495.     public function courseInvoices(
  496.         Request $request,
  497.         Course $course,
  498.         OrderItemRepository $repo,
  499.         OrderService $orderService,
  500.         TagsPersonRepository  $tagsPersonRepository,
  501.     ) {
  502.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  503.         $orderItems $repo->findByCoursePaged($course);
  504.         /**
  505.          * The display logic of subscription courses is different, as there only one order exists per
  506.          * customer/participant, but they should appear in every following course occurrence until they cancel.
  507.          */
  508.         // if ($course->getCourseNature() === 'CourseSubscription') {
  509.         //     return $this->render('course/invoices-subscription.html.twig', [
  510.         //         'course' => $course,
  511.         //         'orderItems' => $orderItems->getIterator(),
  512.         //     ]);
  513.         // } else {
  514.         $archive = !empty($request->get('archive'));
  515.         if ($course->getCourseNature() === 'CourseSubscription') {
  516.             foreach ($orderItems as $orderItem) {
  517.                 $orderItem->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem);
  518.             }
  519.         }
  520.         return $this->render('course/invoices.html.twig', [
  521.             'tagsPerson' => $tagsPersonRepository->findAll(),
  522.             'course' => $course,
  523.             'orderItems' => $orderItems->getIterator(),
  524.             'archive' => $archive,
  525.         ]);
  526.         // }
  527.     }
  528.     /**
  529.      * @Route("/{id}/invoices/create", name="course_create_invoices", methods="POST", requirements={"id"="\d+"})
  530.      */
  531.     public function courseCreateInvoices(
  532.         Request $request,
  533.         Course $course,
  534.         OrderItemRepository $itemRepo,
  535.         InvoiceService $invoiceService
  536.     ) {
  537.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  538.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  539.             $em $this->getDoctrine()->getManager();
  540.             $createIds $request->request->get('create');
  541.             $count 0;
  542.             if (!empty($createIds)) {
  543.                 foreach ($createIds as $id => $value) {
  544.                     if ($value) {
  545.                         $orderItem $itemRepo->find($id);
  546.                         $results $invoiceService->createInvoiceFromOrderItem($orderItem);
  547.                         foreach ($results['attendees'] as $attendee) {
  548.                             $em->persist($attendee);
  549.                         }
  550.                         $em->persist($results['invoice']);
  551.                         $em->flush();
  552.                         $count++;
  553.                     }
  554.                 }
  555.                 $em->flush();
  556.             }
  557.             $this->addFlash('notice'$count . ($count === ' Rechnung' ' Rechnungen') . ' erstellt');
  558.         }
  559.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  560.     }
  561.     /**
  562.      * @Route("/{id}/invoices/merge-pdf", name="course_invoices_merge-pdf", methods="POST", requirements={"id"="\d+"})
  563.      */
  564.     public function courseMergePdf(
  565.         Request $request,
  566.         Course $course,
  567.         OrderItemRepository $repo,
  568.         PdfService $pdfService
  569.     ) {
  570.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  571.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  572.             $em $this->getDoctrine()->getManager();
  573.             $mergeIds $request->request->get('close');
  574.             if (!empty($mergeIds)) {
  575.                 $mergeInvoices = new ArrayCollection();
  576.                 foreach ($mergeIds as $id => $value) {
  577.                     if ($value) {
  578.                         $orderItem $repo->find($id);
  579.                         $order $orderItem->getOrder();
  580.                         foreach ($order->getInvoices() as $invoice) {
  581.                             if (!$mergeInvoices->contains($invoice)) {
  582.                                 $mergeInvoices->add($invoice);
  583.                             }
  584.                         }
  585.                     }
  586.                 }
  587.                 $pdf $pdfService->getMergedInvoicePdf($this->getCurrentClient(), $mergeInvoices->toArray());
  588.                 $pdf->Output('D''Rechnungen_' date('Y-m-d_H-i') . '.pdf');
  589.                 die;
  590.             } else {
  591.                 $this->addFlash('notice''Keine Rechnungen ausgewählt.');
  592.             }
  593.         }
  594.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  595.     }
  596.     /**
  597.      * @Route("/{id}/invoices/close", name="course_close_invoices", methods="POST", requirements={"id"="\d+"})
  598.      */
  599.     public function courseCloseInvoices(
  600.         Request $request,
  601.         Course $course,
  602.         InvoiceItemRepository $repo,
  603.         ConfigurationService $configService,
  604.         MailerService $mailer,
  605.         PdfService $pdfService,
  606.         EmailHistoryService $emailHistoryService
  607.     ) {
  608.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  609.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  610.             $em $this->getDoctrine()->getManager();
  611.             $closeIds $request->request->get('close');
  612.             $count 0;
  613.             if (!empty($closeIds)) {
  614.                 foreach ($closeIds as $id => $value) {
  615.                     if ($value) {
  616.                         $invoiceItem $repo->findOneBy(['orderItem' => $id]);
  617.                         $invoice $invoiceItem->getInvoice();
  618.                         if ($invoice->getStatus() == Invoice::STATUS_DRAFT) {
  619.                             $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  620.                             $sentMessage $mailer->sendInvoiceEmail(
  621.                                 $invoice,
  622.                                 'Rechnung-' $invoice->getNumber() . '.pdf',
  623.                                 $pdf->Output('S''Rechnung-' $invoice->getNumber() . '.pdf')
  624.                             );
  625.                             $outputfile $this->generateUniqueFileName() . '.pdf';
  626.                             $outputpath $this->getParameter('attachment_directory') . '/' $outputfile;
  627.                             $pdf->Output('F'$outputpath);
  628.                             $emailHistoryService->saveProtocolEntryFromInvoiceMessage(
  629.                                 $invoice,
  630.                                 $sentMessage['sender'],
  631.                                 $sentMessage['subject'],
  632.                                 $sentMessage['message'],
  633.                                 $outputfile,
  634.                                 'Rechnung-' $invoice->getNumber() . '.pdf'
  635.                             );
  636.                             if ($invoice->getStatus() != Invoice::STATUS_CLOSED) {
  637.                                 if ($invoice->isPaymentDebit()) {
  638.                                     $invoice->setStatus(Invoice::STATUS_DEBIT_PENDING);
  639.                                 } else {
  640.                                     $invoice->setStatus(Invoice::STATUS_CLOSED);
  641.                                 }
  642.                             }
  643.                             $count++;
  644.                         } else {
  645.                             // Send invoice again
  646.                             $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  647.                             $sentMessage $mailer->sendInvoiceEmail(
  648.                                 $invoice,
  649.                                 'Rechnung-' $invoice->getNumber() . '.pdf',
  650.                                 $pdf->Output('S''Rechnung-' $invoice->getNumber() . '.pdf')
  651.                             );
  652.                             $count++;
  653.                         }
  654.                         //Update the order status
  655.                         $newOrderState $invoice->getOrder()->setStatus(Order::STATUS_DONE);
  656.                         $em->persist($newOrderState);
  657.                         $em->flush();
  658.                     }
  659.                 }
  660.             }
  661.             $this->addFlash('notice'$count . ($count === ' Rechnung' ' Rechnungen') . ' versendet');
  662.         }
  663.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  664.     }
  665.     /**
  666.      * @Route("/{id}/invoices/close-sepa/{all}", name="course_close_sepa-invoices", defaults={"all"="false"},methods="POST", requirements={"id"="\d+"})
  667.      */
  668.     public function courseCloseSepaInvoices(
  669.         Request $request,
  670.         Course $course,
  671.         $all false,
  672.         OrderRepository $repo,
  673.         OrderItemRepository $itemRepo,
  674.         ConfigurationService $configService,
  675.         SepaXmlService $sepaXmlService
  676.     ) {
  677.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  678.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  679.             $em $this->getDoctrine()->getManager();
  680.             $closeIds $request->request->get('close');
  681.             $invoicesToExport = new ArrayCollection();
  682.             if ($all) {
  683.                 $orderItems $itemRepo->findByCoursePaged($course);
  684.                 foreach ($orderItems as $orderItem) {
  685.                     $order $orderItem->getOrder();
  686.                     foreach ($order->getInvoices() as $invoice) {
  687.                         if (
  688.                             $invoice->containsCourse($course) &&
  689.                             !$invoicesToExport->contains($invoice) &&
  690.                             $invoice->isPaymentDebit()
  691.                         ) {
  692.                             $invoicesToExport->add($invoice);
  693.                             $invoice->setStatus(Invoice::STATUS_CLOSED);
  694.                             if (!$order->getCustomer()->getDebitActive()) {
  695.                                 $order->getCustomer()->setDebitActive(true);
  696.                                 $invoice->setIsNewSepaMandate(true);
  697.                             }
  698.                         }
  699.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  700.                             $restsumme $invoice->getMissingSum();
  701.                             if ($restsumme != 0) {
  702.                                 $invoicePayment = new InvoicePayment();
  703.                                 $invoicePayment->setInvoice($invoice);
  704.                                 $invoicePayment->setPayedDate(new \DateTime());
  705.                                 $invoicePayment->setSum($invoice->getMissingSum());
  706.                                 $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  707.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  708.                                 $em $this->getDoctrine()->getManager();
  709.                                 $em->persist($invoicePayment);
  710.                             }
  711.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  712.                             $invoice->setExportStatus(Invoice::EXPORTED);
  713.                             $em->persist($invoice);
  714.                             $em->flush();
  715.                         }
  716.                     }
  717.                 }
  718.             } elseif (!empty($closeIds)) {
  719.                 foreach ($closeIds as $id => $value) {
  720.                     if ($value) {
  721.                         $orderItem $itemRepo->find($id);
  722.                         $order $orderItem->getOrder();
  723.                         foreach ($order->getInvoices() as $invoice) {
  724.                             if (
  725.                                 $invoice->containsCourse($course) &&
  726.                                 !$invoicesToExport->contains($invoice) &&
  727.                                 $invoice->isPaymentDebit()
  728.                             ) {
  729.                                 $invoicesToExport->add($invoice);
  730.                                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  731.                                 if (!$order->getCustomer()->getDebitActive()) {
  732.                                     $order->getCustomer()->setDebitActive(true);
  733.                                     $invoice->setIsNewSepaMandate(true);
  734.                                 }
  735.                             }
  736.                         }
  737.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  738.                             $restsumme $invoice->getMissingSum();
  739.                             if ($restsumme != 0) {
  740.                                 $invoicePayment = new InvoicePayment();
  741.                                 $invoicePayment->setInvoice($invoice);
  742.                                 $invoicePayment->setPayedDate(new \DateTime());
  743.                                 $invoicePayment->setSum($invoice->getMissingSum());
  744.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  745.                                 $em $this->getDoctrine()->getManager();
  746.                                 $em->persist($invoicePayment);
  747.                             }
  748.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  749.                             $invoice->setExportStatus(Invoice::EXPORTED);
  750.                             $em->persist($invoice);
  751.                             $em->flush();
  752.                         }
  753.                     }
  754.                 }
  755.             } else {
  756.                 $this->addFlash('warning''Es wurden keine Rechnungen zum Export ausgewählt.');
  757.                 return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  758.             }
  759.             // Check invoices for past due dates
  760.             foreach ($invoicesToExport as $invoice) {
  761.                 if (new \DateTime() > $invoice->getDueDate()) {
  762.                     $this->addFlash('warning''Mindestens eine Rechnung enthält ein Zahlungsziel in der Vergangenheit.');
  763.                     // return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  764.                 }
  765.             }
  766.             if (count($invoicesToExport) > 0) {
  767.                 $config $configService->getSepaXmlConfigByClient($this->getCurrentClient());
  768.                 try {
  769.                     $xml $sepaXmlService->getSepaXmlMultiple($this->getCurrentClient(), $config$invoicesToExport);
  770.                 } catch (ServiceException $e) {
  771.                     $this->addFlash('error'$e->getMessage());
  772.                     return $this->redirectToRoute('invoice_index');
  773.                 }
  774.                 $em->flush();
  775.                 $response = new Response($xml);
  776.                 $response->headers->set('Content-Type''text/xml');
  777.                 $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  778.                 return $response;
  779.             }
  780.             $this->addFlash('error''Mindestens eine Rechnung enthält Fehler.');
  781.             return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  782.         }
  783.         $this->addFlash('error''Der Sicherheits-Token ist ungültig. Bitte versuchen Sie es noch einmal.');
  784.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  785.     }
  786.     /**
  787.      * @Route("/{id}/invoices/close-sepa/", name="course_close_sepa-invoice_selected", methods="POST", requirements={"id"="\d+"})
  788.      */
  789.     public function courseCloseSepaInvoiceSelected(
  790.         Request $request,
  791.         Course $course,
  792.         OrderItemRepository $itemRepo,
  793.         ConfigurationService $configService,
  794.         SepaXmlService $sepaXmlService
  795.     ) {
  796.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  797.         if ($this->isCsrfTokenValid('create_invoices'$request->request->get('_token'))) {
  798.             $em $this->getDoctrine()->getManager();
  799.             $closeIds $request->request->get('close');
  800.             $invoicesToExport = new ArrayCollection();
  801.         if (!empty($closeIds)) {
  802.                 foreach ($closeIds as $id => $value) {
  803.                     if ($value) {
  804.                         $orderItem $itemRepo->find($id);
  805.                         $order $orderItem->getOrder();
  806.                         foreach ($order->getInvoices() as $invoice) {
  807.                             if (
  808.                                 $invoice->containsCourse($course) &&
  809.                                 !$invoicesToExport->contains($invoice) &&
  810.                                 $invoice->isPaymentDebit()
  811.                             ) {
  812.                                 $invoicesToExport->add($invoice);
  813.                                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  814.                                 if (!$order->getCustomer()->getDebitActive()) {
  815.                                     $order->getCustomer()->setDebitActive(true);
  816.                                     $invoice->setIsNewSepaMandate(true);
  817.                                 }
  818.                             }
  819.                         }
  820.                         if (!empty($_ENV['SEPAEXPORT_PAYED'])) {
  821.                             $restsumme $invoice->getMissingSum();
  822.                             if ($restsumme != 0) {
  823.                                 $invoicePayment = new InvoicePayment();
  824.                                 $invoicePayment->setInvoice($invoice);
  825.                                 $invoicePayment->setPayedDate(new \DateTime());
  826.                                 $invoicePayment->setSum($invoice->getMissingSum());
  827.                                 $invoice->setExportStatus(Invoice::EXPORTED);
  828.                                 $em $this->getDoctrine()->getManager();
  829.                                 $em->persist($invoicePayment);
  830.                             }
  831.                             $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  832.                             $invoice->setExportStatus(Invoice::EXPORTED);
  833.                             $em->persist($invoice);
  834.                             $em->flush();
  835.                         }
  836.                     }
  837.                 }
  838.             } else {
  839.                 $this->addFlash('warning''Es wurden keine Rechnungen zum Export ausgewählt.');
  840.                 return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  841.             }
  842.             // Check invoices for past due dates
  843.             foreach ($invoicesToExport as $invoice) {
  844.                 if (new \DateTime() > $invoice->getDueDate()) {
  845.                    
  846.                     $this->addFlash('warning''Mindestens eine Rechnung enthält ein Zahlungsziel in der Vergangenheit.');
  847.                     // return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  848.                 }
  849.             }
  850.             if (count($invoicesToExport) > 0) {
  851.                 $config $configService->getSepaXmlConfigByClient($this->getCurrentClient());
  852.                 try {
  853.                     $xml $sepaXmlService->getSepaXmlMultiple($this->getCurrentClient(), $config$invoicesToExport);
  854.                 } catch (ServiceException $e) {
  855.                     $this->addFlash('error'$e->getMessage());
  856.                     return $this->redirectToRoute('invoice_index');
  857.                 }
  858.                 $em->flush();
  859.                 $response = new Response($xml);
  860.                 $response->headers->set('Content-Type''text/xml');
  861.                 $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  862.                 return $response;
  863.             }
  864.             $this->addFlash('error''Mindestens eine Rechnung enthält Fehler.');
  865.             return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  866.         }
  867.         $this->addFlash('error''Der Sicherheits-Token ist ungültig. Bitte versuchen Sie es noch einmal.');
  868.         return $this->redirectToRoute('course_invoices', ['id' => $course->getId()]);
  869.     }
  870.     /**
  871.      * @Route("/{id}/participants", name="course_participants", methods="GET", requirements={"id"="\d+"})
  872.      */
  873.     public function courseParticipants(
  874.         Request $request,
  875.         Course $course,
  876.         OrderItemRepository $repo,
  877.         OrderService $orderService,
  878.         TagsPersonRepository  $tagsPersonRepository,
  879.     ) {
  880.       //  $this->denyAccessUnlessGranted('ROLE_MANAGER', $course);
  881.         $orderItems $repo->findByCoursePaged($course);
  882.       
  883.         $archive = !empty($request->get('archive'));
  884.         if ($course->getCourseNature() === 'CourseSubscription') {
  885.             foreach ($orderItems as $orderItem) {
  886.                 foreach ($orderItem->getParticipants() as $participant) {
  887.                     $participant->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem$participant->getId());
  888.                     $participant->cancelDate $orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant);
  889.                 }
  890.             }
  891.         }
  892.         return $this->render('course/participants.html.twig', [
  893.             'tagsPerson' => $tagsPersonRepository->findAll(),
  894.             'env' => $_ENV,
  895.             'course' => $course,
  896.             'orderItems' => $orderItems->getIterator(),
  897.             'showCertificatesLink' => !empty($_ENV['CERTIFICATES_ENABLED']),
  898.             'archive' => $archive,
  899.         ]);
  900.       
  901.     }
  902.     /**
  903.      * @Route("/{id}/participants-pdf/{page}/{orderby}/{order}", name="course_participants_pdf", methods="GET", requirements={"id"="\d+"})
  904.      * @IsGranted("ROLE_SPEAKER")
  905.      */
  906.     public function courseParticipantsPdf(
  907.         Request $request,
  908.         CourseOccurrence $courseOccurrence,
  909.         OrderItemRepository $repo,
  910.         PdfService $pdfService,
  911.         OrderService $orderService,
  912.         $page 1,
  913.         $orderby 'customerLastname',
  914.         $order 'asc'
  915.     ) {
  916.         //    $this->denyAccessUnlessGranted('client_allowed', $courseOccurrence);
  917.         $this->denyAccessUnlessGranted('ROLE_SPEAKER'$courseOccurrence);
  918.         $orderItems $repo->findByCourseOccurrence($courseOccurrence$orderby$order);
  919.         if ($courseOccurrence->getCourse()->getCourseNature() === 'CourseSubscription') {
  920.             foreach ($orderItems as $orderItem) {
  921.                 foreach ($orderItem->getParticipants() as $participant) {
  922.                     $participant->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem$participant->getId());
  923.                 }
  924.             }
  925.         }
  926.         $pdf $pdfService->getParticipantsPdf($this->getCurrentClient(), $courseOccurrence$orderItems);
  927.         $pdf->Output('D''Teilnehmerliste-' $courseOccurrence->getStart()->format('Y-m-d') . '.pdf');
  928.         exit();
  929.     }
  930.     /**
  931.      * @Route("/participant/{id}/certificateemail", name="course_participants_certificate_email", methods="GET", requirements={"id"="\d+","downlaod"="\d+"})
  932.      */
  933.     public function courseParticipantsCertificateEmail(
  934.         Request $request,
  935.         $id,
  936.         ConfigurationService $configService,
  937.         OrderItemPerson $orderItemPerson,
  938.         TextblocksRepository $textblocksRepository,
  939.         CourseDataRepository $courseDataRepository,
  940.         OrderItemRepository $repo
  941.     ): Response {
  942. $orderItem $repo->find($id);
  943.         $currentUrl $request->getUri();
  944.         // $orderItemPerson = $orderItemPersonRepository->find($id);
  945.          $this->certificateService->generateAndSendCertificate(
  946.             $request,
  947.             $orderItemPerson->getOrderItem()->getOrder()->getNumber().'-von-'.count($orderItemPerson->getOrderItem()->getParticipants()),  // Beispiel-ID, ändern je nach Datenstruktur
  948. //            $id,
  949.             $configService,
  950.             $orderItemPerson,
  951.             $textblocksRepository,
  952.             $courseDataRepository,
  953.             $repo
  954.         );
  955.     return $this->redirectToRoute('course_participants', ['id' => $orderItemPerson->getOrderItem()->getCourse()->getId()]);
  956.        
  957.     }
  958. /**
  959.      * @Route("/{id}/presences", name="course_presences", methods="GET", requirements={"id"="\d+"})
  960.      */
  961.     public function coursePresences(
  962.         Request $request,
  963.         Course $course,
  964.         OrderItemRepository $repo,
  965.         OrderService $orderService,
  966.         CourseOccurrenceRepository $occurrencesrepo,
  967.         TagsPersonRepository  $tagsPersonRepository,
  968.         \App\Service\UiService $uiService,
  969.         PresenceRepository $presenceRepository,
  970.     ) {
  971.         $this->denyAccessUnlessGranted('ROLE_SPEAKER'$course);
  972.         $orderItems $repo->findByCoursePaged($course);
  973.         $order $uiService->getSortOrder('course-occurrences-listing');
  974.       
  975.         $archive = !empty($request->get('archive'));
  976.         if ($course->getCourseNature() === 'CourseSubscription') {
  977.             foreach ($orderItems as $orderItem) {
  978.                 foreach ($orderItem->getParticipants() as $participant) {
  979.                     $participant->isAfterCancelDate $orderService->isOrderItemOccurrenceAfterCancelDateByParticipant($this->getCurrentClient(), $orderItem$participant->getId());
  980.                     $participant->cancelDate $orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant);
  981.                 }
  982.             }
  983.         }
  984.         $occurrences $occurrencesrepo->findByCoursePaged(
  985.             $course,
  986.             self::LISTING_LIMIT,
  987.             $order['orderDirection'] ?? 'ASC',
  988.             $order['orderBy'] ?? 'title'
  989.         );
  990.         return $this->render('course/presences.html.twig', [
  991.             'presences' => $presenceRepository->findAll(),
  992.             'uiService' => $uiService,
  993.             'tagsPerson' => $tagsPersonRepository->findAll(),
  994.             'env' => $_ENV,
  995.             'course' => $course,
  996.             'occurrences' => $occurrences->getIterator(), 
  997.             'total' => $occurrences->count(),
  998.             'pages' => ceil($occurrences->count() / self::LISTING_LIMIT),
  999.             'page' => 1,
  1000.             'orderItems' => $orderItems->getIterator(),
  1001.             'showCertificatesLink' => !empty($_ENV['CERTIFICATES_ENABLED']),
  1002.             'archive' => $archive,
  1003.         ]);
  1004.         
  1005.     }
  1006.     /**
  1007.      * @Route("/coursepresence/{id}/add/{courseOccurrence}/{participant}", name="course_presence_add", methods="GET|POST")
  1008.      */
  1009.                         
  1010.      public function savePresenseNew(
  1011.         $id,
  1012.         $courseOccurrence,
  1013.         $participant,
  1014.         CourseOccurrenceTimeRepository $occurrenceTimeRepository,
  1015.         CourseOccurrenceRepository  $occurrenceRepository,
  1016.         PersonRepository $personRepository,
  1017.          )
  1018.        {
  1019.         $occurrenceTime $occurrenceTimeRepository->find($id);
  1020.         $occurrence $occurrenceRepository->find($courseOccurrence);
  1021.         $user $this->getCurrentUser();
  1022.         $person $personRepository->find($participant);
  1023.            $newpresence = new Presence();
  1024.            
  1025.            $newpresence->setOccurrence($occurrence);
  1026.            $newpresence->setOccurrenceTime($occurrenceTime);
  1027.            $newpresence->setUser($user);
  1028.            $newpresence->setPerson($person);
  1029.            $newpresence->setPresence('1');
  1030.            $newpresence->setCreated(new \Datetime());
  1031.            $newpresence->setClient($this->getCurrentClient());
  1032.            $this->managerRegistry->persist($newpresence);
  1033.             $this->managerRegistry->flush();
  1034.            
  1035.             return $this->json([
  1036.                 'success' => "Die Anwesenheit wurde eingetragen.",
  1037.                 'presence' => true,
  1038.             ]);
  1039.        }
  1040.      /**
  1041.      * @Route("/coursepresence/{id}/delete", name="course_presence_delete", methods="GET|POST")
  1042.      */
  1043.                         
  1044.      public function deletePresense(
  1045.         $id,
  1046.         PresenceRepository $presenceRepository,
  1047.         
  1048.                ): Response
  1049.        {
  1050.         $presence $presenceRepository->find($id);  
  1051.       // $presenceRepository->remove($presenceremove);
  1052.         $presence->setPresence('0');
  1053.         $presence->setModified(new \Datetime());
  1054.          $this->managerRegistry->persist($presence);
  1055.          $this->managerRegistry->flush();
  1056.            
  1057.             return $this->json([
  1058.                 'success' => "Die Anwesenheit wurde ausgetragen.",
  1059.                 'presence' => true,
  1060.             ]);
  1061.        }
  1062.      /**
  1063.      * @Route("/coursepresence/{id}/edit", name="course_presence_edit", methods="GET|POST")
  1064.      */
  1065.                         
  1066.      public function editPresense(
  1067.         $id,
  1068.         PresenceRepository $presenceRepository,
  1069.         
  1070.                ): Response
  1071.        {
  1072.         $presence $presenceRepository->find($id);  
  1073.       // $presenceRepository->remove($presenceremove);
  1074.         $presence->setReason('x');
  1075.         $presence->setModified(new \Datetime());
  1076.          $this->managerRegistry->persist($presence);
  1077.          $this->managerRegistry->flush();
  1078.            
  1079.             return $this->json([
  1080.                 'success' => "Der Grund wurde eingetragen.",
  1081.             ]);
  1082.        }
  1083. /**
  1084.  * @Route("/coursepresence/{id}/update", name="course_presence_update", methods="GET|POST")
  1085.  */
  1086. public function updatePresence(Request $request): JsonResponse
  1087.     {
  1088.         // JSON-Daten aus der Anfrage extrahieren
  1089.         $data json_decode($request->getContent(), true);
  1090.         $id $data['id'] ?? null;
  1091.         $value $data['value'] ?? null;
  1092.         if ($id === null || $value === null) {
  1093.             return new JsonResponse(['success' => false'message' => 'Invalid data'], 400);
  1094.         }
  1095.         // Hier können Sie die Logik für das Aktualisieren der Anwesenheit implementieren
  1096.         // Zum Beispiel: Suchen Sie das entsprechende Entity und aktualisieren Sie den Wert
  1097.         $entityManager $this->getDoctrine()->getManager();
  1098.         $presence $entityManager->getRepository(Presence::class)->find($id);
  1099.         if (!$presence) {
  1100.             return new JsonResponse(['success' => false'message' => 'Presence not found'], 404);
  1101.         }
  1102.         // Setzen Sie den neuen Wert und speichern Sie ihn
  1103.         $presence->setreason($value); // Beispiel: setValue() sollte zu Ihrem Entity passen
  1104.         $entityManager->persist($presence);
  1105.         $entityManager->flush();
  1106.         // Erfolgreiche Antwort zurückgeben
  1107.         return new JsonResponse(['success' => true]);
  1108.     }
  1109.      /**
  1110.      * @Route("/coursepresence/{id}/participantspresenceexport", name="course_participants_presences_export", methods="GET", requirements={"id"="\d+"})
  1111.      * @IsGranted("ROLE_SPEAKER")
  1112.      */
  1113.     public function courseParticipantsPresencesExport(
  1114.         Request $request,
  1115.              
  1116.         CourseOccurrence $courseOccurrence,
  1117.         OrderItemRepository $repo,
  1118.         PresenceRepository $presenceRepository,
  1119.         CourseOccurrenceTimeRepository $occurrenceTimeRepository,
  1120.         CourseOccurrenceRepository  $occurrenceRepository,
  1121.        
  1122.         $orderby 'customerLastname',
  1123.         $order 'asc'
  1124.     ) {
  1125.        $this->denyAccessUnlessGranted('ROLE_SPEAKER'$courseOccurrence);
  1126.         $orderItems $repo->findByCourseOccurrence($courseOccurrence$orderby$order);
  1127.          $course $courseOccurrence->getCourse()->getId();
  1128.          $orderItems $repo->findByCourseOccurrence($courseOccurrence$orderby$order);
  1129.  
  1130.          $response $this->render('person/export-participants-presences.csv.twig', [
  1131.             'presences' => $presenceRepository->findByOccurrence($courseOccurrence),
  1132.             'course' => $course,
  1133.              'occurrence' => $courseOccurrence
  1134.             'orderItems' => $orderItems,
  1135.           
  1136.         ]);
  1137.         $response->setStatusCode(200);
  1138.         $response->headers->set('Content-Type''text/csv; charset=utf-8');
  1139.        
  1140.         $response->headers->set('Content-Disposition''attachment; filename="Anwesenheit_Kurs.csv"');
  1141.         
  1142.         return $response;
  1143.         
  1144.     }
  1145.      /**
  1146.      * @Route("/coursepresence/{id}/exportcourseparticipants", name="export_course_participants", methods="GET", requirements={"id"="\d+"})
  1147.      * @IsGranted("ROLE_SPEAKER")
  1148.      */
  1149.     public function courseParticipantsExport(
  1150.         Request $request,
  1151.         CourseOccurrence $courseOccurrence,
  1152.         OrderItemRepository $repo,
  1153.         $orderby 'customerLastname',
  1154.         $order 'asc'
  1155.     ) {
  1156.        $this->denyAccessUnlessGranted('ROLE_SPEAKER'$courseOccurrence);
  1157.        
  1158.        $header $request->get('header'false); // Holen Sie den Wert von 'header'
  1159.     // Wenn 'header' true ist, setzen Sie ihn auf 1
  1160.     if ($header) {
  1161.         $header '1';
  1162.     } else
  1163.     { $header '0';}
  1164.          $course $courseOccurrence->getCourse()->getId();
  1165.          $orderItems $repo->findByCourseOccurrence($courseOccurrence$orderby$order);
  1166.     
  1167.          
  1168.          // Rendern des CSV-Inhalts als String (UTF-8)
  1169.            $csvContent $this->renderView('person/export-course-participants.csv.twig', [
  1170.            
  1171.             'header' => $header,
  1172.             'course' => $course,
  1173.             'occurrence' => $courseOccurrence
  1174.             'orderItems' => $orderItems,
  1175.             ]);
  1176.           // Konvertiere den CSV-Inhalt in ISO-8859-1
  1177.           $encodedCsvContent mb_convert_encoding($csvContent'ISO-8859-1''UTF-8');
  1178.              // Erstelle eine Antwort mit dem konvertierten Inhalt
  1179.              $response = new Response($encodedCsvContent); 
  1180.             $response->setStatusCode(200);
  1181.             $response->headers->set('Content-Type''text/csv; charset=ISO-8859-1');
  1182.     //        $response->headers->set('Content-Type', 'text/csv; charset=utf-8');
  1183.         $startDate $courseOccurrence->getStart();
  1184.         $formattedDate $startDate->format('d.m.y');
  1185.         // Konstruktion des Dateinamens
  1186.         $courseTitle $courseOccurrence->getCourse()->getTitle();
  1187.         $fileName 'Kurs-Teilnehmer-' $courseTitle '-' $formattedDate '.csv';
  1188.         // Setzen des Content-Disposition-Headers
  1189.         $response->headers->set('Content-Disposition''attachment; filename="' $fileName '"');
  1190.         return $response;
  1191.         
  1192.         
  1193.     }
  1194.     /**
  1195.      * @Route("/{id}/reservations", name="course_reservations", methods="GET", requirements={"id"="\d+"})
  1196.      */
  1197.     public function courseReservations(
  1198.         Request $request,
  1199.         Course $course,
  1200.         WaitItemRepository $repo,
  1201.         TagsPersonRepository  $tagsPersonRepository,
  1202.     ) {
  1203.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  1204.         $waitItems $repo->findByCoursePaged($course);
  1205.         return $this->render('course/reservations.html.twig', [
  1206.             'course' => $course,
  1207.             'waitItems' => $waitItems->getIterator(),
  1208.             'tagsPerson' => $tagsPersonRepository->findAll(),
  1209.         ]);
  1210.     }
  1211.     /**
  1212.      * @Route("/waititem/{id}/delete", name="waititem_delete", methods="GET|POST")
  1213.      */
  1214.     public function deleteWaitItem($id,  
  1215.    
  1216.     WaitItemRepository $waitItemRepository,
  1217.     TagsPersonRepository  $tagsPersonRepository,
  1218.     EntityManagerInterface $entityManager): Response
  1219.     {
  1220.         $waitItem $waitItemRepository->find($id);
  1221.         
  1222.         $course $waitItem->getCourseOccurrence()->getCourse();
  1223.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  1224.         $waitItems $waitItemRepository->findByCoursePaged($course);
  1225.         if (!$waitItem) {
  1226.             throw $this->createNotFoundException('WaitItem not found');
  1227.         }
  1228.         $entityManager->remove($waitItem);
  1229.         $entityManager->flush();
  1230.         $this->addFlash('success''WaitItem deleted successfully');
  1231.         return $this->render('course/reservations.html.twig', [
  1232.             'course' => $course,
  1233.             'waitItems' => $waitItems->getIterator(),
  1234.             'tagsPerson' => $tagsPersonRepository->findAll(),
  1235.         ]);
  1236.     }
  1237.     /**
  1238.      * @Route("/{id}/reservations/move", name="course_reservations_move", methods="POST", requirements={"id"="\d+"})
  1239.      */
  1240.     public function moveCourseReservations(
  1241.         Request $request,
  1242.         Course $course,
  1243.         WaitItemRepository $repo
  1244.     ): Response {
  1245.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$course);
  1246.         $em $this->getDoctrine()->getManager();
  1247.         $moveIds $request->request->get('item');
  1248.         foreach ($moveIds as $id => $value) {
  1249.             if ($value) {
  1250.                 $waitItem $repo->find($value);
  1251.                 $orderItem OrderItem::createFromWaitItem($waitItem);
  1252.                 $participants $waitItem->getParticipants();
  1253.                 foreach ($participants as $participant) {
  1254.                     if ($participant->getPerson()->getId() === $id) {
  1255.                         $participant->setWaitItem(null);
  1256.                         $participant->setOrderItem($orderItem);
  1257.                         $orderItem->setQuantity($orderItem->getQuantity() + 1);
  1258.                         $waitItem->setQuantity($waitItem->getQuantity() - 1);
  1259.                         break;
  1260.                     }
  1261.                 }
  1262.                 $waitItem->getCourseOccurrence()->bookSlots($orderItem->getQuantity());
  1263.                 $order $waitItem->getOrder();
  1264.                 $order->addOrderItem($orderItem);
  1265.                 if ($waitItem->getQuantity() === 0) {
  1266.                     $order->removeWaitItem($waitItem);
  1267.                 }
  1268.                 $em->persist($order);
  1269.             }
  1270.         }
  1271.         $this->addFlash('notice'count($moveIds) . (count($moveIds) > ' Wartelistenplätze verschoben' ' Wartelistenplatz verschoben'));
  1272.         $em->flush();
  1273.         return $this->redirectToRoute('course_reservations',  ['id' => $course->getId()]);
  1274.     }
  1275.     private function generateUniqueFileName()
  1276.     {
  1277.         return md5(uniqid());
  1278.     }
  1279.     private function createDescription($field$option)
  1280.     {
  1281.         switch ($option) {
  1282.             case 'course':
  1283.                 if (!empty($field['certificate'])) {
  1284.                     $field['name'] = $this->generateHTMLForDescription(
  1285.                         $field['name'],
  1286.                         'für den Kurs und das Zertifikat'
  1287.                     );
  1288.                 } else {
  1289.                     $field['name'] = $this->generateHTMLForDescription(
  1290.                         $field['name'],
  1291.                         'für den Kurs'
  1292.                     );
  1293.                 }
  1294.                 break;
  1295.             case 'certificate':
  1296.                 $field['name'] = $this->generateHTMLForDescription(
  1297.                     $field['name'],
  1298.                     'für das Zertifikat'
  1299.                 );
  1300.                 break;
  1301.             default:
  1302.                 break;
  1303.         }
  1304.         return $field;
  1305.     }
  1306.     private function generateHTMLForDescription($name$text)
  1307.     {
  1308.         return '<strong>' $name '</strong>' .  '<span style="font-size: 0.7rem"> (' $text ')</span>';
  1309.     }
  1310. }