src/Controller/OrderController.php line 116

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Order;
  4. use App\Entity\Invoice;
  5. use App\Form\OrderType;
  6. use App\Entity\WaitItem;
  7. use App\Entity\OrderItem;
  8. use App\Service\UiService;
  9. use App\Form\OrderStatusType;
  10. use App\Service\OrderService;
  11. use Doctrine\DBAL\Connection;
  12. use App\Entity\OrderItemPerson;
  13. use App\Service\InvoiceService;
  14. use App\Form\OrderItemPersonCopy;
  15. use App\Repository\OrderRepository;
  16. use App\Repository\PersonRepository;
  17. use App\Repository\InvoiceRepository;
  18. use App\Service\ConfigurationService;
  19. use App\Form\OrderItemPersonCancelDate;
  20. use App\Entity\CourseSubscriptionBooking;
  21. use Doctrine\Persistence\ManagerRegistry;
  22. use Doctrine\Common\Collections\Collection;
  23. use Psr\Log\LoggerInterface;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use App\Repository\CourseOccurrenceRepository;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\Routing\Annotation\Route;
  28. use App\Repository\CourseOccurrenceTimeRepository;
  29. use Symfony\Component\HttpFoundation\RequestStack;
  30. use Menke\UserBundle\Controller\AbstractClientableController;
  31. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  32. /**
  33.  * @Route("/order")
  34.  * @IsGranted("ROLE_MANAGER")
  35.  * @IsGranted("ROLE_ADMIN")
  36.  */
  37. class OrderController extends AbstractClientableController
  38. {
  39.     const LISTING_LIMIT 25;
  40.     /**
  41.      * @Route("/", name="order_index", methods="GET")
  42.      */
  43.     public function index(
  44.         UiService $uiService,
  45.         OrderRepository $orderRepo,
  46.         Request $request,
  47.         RequestStack $requestStack
  48.     ): Response {
  49.         $order $uiService->getSortOrder('order-index-listing');
  50.         $filterOrders $request->get('orderAction');
  51.         if ($filterOrders) {
  52.             $requestStack->getSession()->set('orderFilter'$filterOrders);
  53.         } else {
  54.             $requestStack->getSession()->set('orderFilter'null);
  55.         }
  56.         $orders $orderRepo->getByClientPaged(
  57.             $this->getCurrentClient(),
  58.             self::LISTING_LIMIT,
  59.             $order['orderDirection'] ?? 'desc',
  60.             $order['orderBy'] ?? 'date',
  61.             1,
  62.             ($filterOrders) ? $filterOrders null
  63.         );
  64.         return $this->render('order/index.html.twig', [
  65.             'uiService' => $uiService,
  66.             'orders' => $orders->getIterator(),
  67.             'total' => $orders->count(),
  68.             'pages' => ceil($orders->count() / self::LISTING_LIMIT),
  69.             'page' => 1,
  70.         ]);
  71.     }
  72.     /**
  73.      * @Route("/{page}/{orderby}/{order}", name="order_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
  74.      */
  75.     public function indexListing(
  76.         OrderRepository $orderRepo,
  77.         UiService $uiService,
  78.         $page,
  79.         $orderby,
  80.         $order,
  81.         RequestStack $requestStack
  82.     ): Response {
  83.         $uiService->storeSortOrder('order-index-listing'$orderby$order);
  84.         $orders $orderRepo->getByClientPaged(
  85.             $this->getCurrentClient(),
  86.             self::LISTING_LIMIT,
  87.             $order,
  88.             $orderby,
  89.             $page,
  90.             $requestStack->getSession()->get('orderFilter')
  91.         );
  92.         return $this->render('order/_index_listing.html.twig', [
  93.             'orders' => $orders->getIterator(),
  94.             'total' => $orders->count(),
  95.             'pages' => ceil($orders->count() / self::LISTING_LIMIT),
  96.             'page' => $page,
  97.         ]);
  98.     }
  99.     /**
  100.      * @Route("/new/{return}", name="order_new", methods="GET|POST")
  101.      */
  102.     public function new(
  103.         Request $request,
  104.         $return '',
  105.         PersonRepository $personRepo,
  106.         ConfigurationService $configService,
  107.         OrderService $orderService,
  108.         CourseOccurrenceRepository $courseOccurrenceRepository
  109.     ): Response {
  110.         $customer null;
  111.         $invoiceRecipient null;
  112.         $isEmptyParticipants false;
  113.         if ($return) {
  114.             $customer $personRepo->find($return);
  115.             $invoiceRecipient $personRepo->getInvoiceReciepientMembers($return);
  116.             $invoiceRecipient $this->createInvoiceRecipientValues($invoiceRecipient$customer);
  117.             $customerChildrens $personRepo->getMembersByClient($customer);
  118.             $isEmptyParticipants = (empty($customerChildrens)) ? true false;
  119.         }
  120.         $order = new Order();
  121.         $form $this->createForm(OrderType::class, $order, [
  122.             'client' => $this->getCurrentClient(),
  123.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  124.             'customer' => $customer,
  125.             'invoiceRecipient' => $invoiceRecipient,
  126.             'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
  127.         ]);
  128.         $form->handleRequest($request);
  129.         // Check if creation is possible
  130.         if ($form->isSubmitted() && $form->isValid()) {
  131.             foreach ($order->getOrderItems() as $orderItem) {
  132.                 // Skip participants check for free items
  133.                 if ($orderItem->getCourseOccurrence() === null) {
  134.                     continue;
  135.                 }
  136.                 // Check if order item has at least one participant
  137.                 if (count($orderItem->getParticipants()) == 0) {
  138.                     $this->addFlash('error''Der Kurs enthält keine Teilnehmer.');
  139.                     return $this->redirectToRoute('order_new', ['return' => $return]);
  140.                 }
  141.             }
  142.             if (!$order->checkCustomerData($customer)) {
  143.                 $this->addFlash('error''Die Kundendaten sind unvollständig. Es kann keine neue Bestellung angelegt werden.');
  144.                 if ($return) {
  145.                     return $this->redirectToRoute('customer_orders', ['id' => $return]);
  146.                 } else {
  147.                     return $this->redirectToRoute('order_index');
  148.                 }
  149.             }
  150.             $em $this->getDoctrine()->getManager();
  151.             $allItemsBookable true;
  152.             $occurrences = [];
  153.             foreach ($order->getOrderItems() as $orderItem) {
  154.                 if ($orderItem->getCourseOccurrence()) {
  155.                     $occurrence $orderItem->getCourseOccurrence();
  156.                     if (!$occurrence->isBookable($orderItem->getQuantity()) && $occurrence->getReservationAllowed()) {
  157.                         $waitItem WaitItem::fromOrderItem($orderItem);
  158.                         $em->persist($waitItem);
  159.                         foreach ($orderItem->getParticipants() as $participant) {
  160.                             $orderItem->removeParticipant($participant);
  161.                         }
  162.                         $order->addWaitItem($waitItem);
  163.                         $order->removeOrderItem($orderItem);
  164.                         $this->addFlash('error''Im Kurs "' $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar. Die Buchung wurde stattdessen zur Warteliste hinzugefügt.');
  165.                     } elseif (!$occurrence->isBookable($orderItem->getQuantity()) && !$occurrence->getReservationAllowed()) {
  166.                         $allItemsBookable false;
  167.                         $this->addFlash('error''Im Kurs "' $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar.');
  168.                     } else {
  169.                         if ($orderItem->getCourseOccurrence()->getCourse()->getCourseNature() == 'CourseSubscription') {
  170.                             $courseSubscriptionBooking = new CourseSubscriptionBooking($orderItem$orderItem->getCourse());
  171.                             $courseSubscriptionBooking->setOrderItem($orderItem);
  172.                             $courseSubscriptionBooking->setCourse($orderItem->getCourseOccurrence()->getCourse());
  173.                             $courseSubscriptionBooking->setCourseSubscription($orderItem->getCourseOccurrence()->getCourse()->getSubscription());
  174.                             $orderItem->setCourseSubscriptionBooking($courseSubscriptionBooking);
  175.                             $em->persist($courseSubscriptionBooking);
  176.                         }
  177.                         $occurrence->bookSlots($orderItem->getQuantity());
  178.                         $occurrences[] = $occurrence;
  179.                     }
  180.                 }
  181.             }
  182.             $this->updateParticipantsOfOrder($order);
  183.             $em->flush();
  184.             if ($allItemsBookable) {
  185.                 if (count($order->getOrderItems()) > ||  count($order->getWaitItems()) > 0) {
  186.                     $order->setClient($this->getCurrentClient());
  187.                     $order->setCustomer($customer);
  188.                     $order->setCustomerData($customer);
  189.                     $order->setNumber($configService->getNewOrderNumberByClient($this->getCurrentClient()));
  190.                     $em->persist($order);
  191.                     $em->flush();
  192.                     foreach ($occurrences as $occurrence) {
  193.                         $occurrence->flushBooking();
  194.                     }
  195.                     // Ggf. nachfolgende Bestellungen fuer Abokurse generieren und speichern
  196.                     $flashs = [];
  197.                     $followingOrders $orderService->generateOrdersForSubscriptionCoursesAllFollowingOccurrences($this->getCurrentClient(), $order$flashs);
  198.                     foreach ($followingOrders as $orderToSave) {
  199.                         $em->persist($orderToSave);
  200.                     }
  201.                     foreach ($flashs as $flashToShow) {
  202.                         foreach ($flashToShow as $key => $value) {
  203.                             $this->addFlash($key$value);
  204.                         }
  205.                     }
  206.                     $em->flush();
  207.                 }
  208.                 if ($return) {
  209.                     return $this->redirectToRoute('customer_orders', ['id' => $return]);
  210.                 } else {
  211.                     return $this->redirectToRoute('order_index');
  212.                 }
  213.             }
  214.         }
  215.         return $this->render('order/new.html.twig', [
  216.             'order' => $order,
  217.             'form' => $form->createView(),
  218.             'customer' => $customer,
  219.             'invoiceRecipient' => $invoiceRecipient,
  220.             'invalidCustomerData' => !$order->checkCustomerData($customer),
  221.             'isEmptyParticipants' => $isEmptyParticipants,
  222.             'isInvoiceClosed' => false
  223.         ]);
  224.     }
  225.     /**
  226.      * @Route("/{id}", name="order_show", methods="GET|POST", requirements={"id"="\d+"})
  227.      */
  228.     public function show(
  229.         Request $request,
  230.         Order $order,
  231.         InvoiceRepository $invoiceRepo
  232.     ): Response {
  233.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  234.         $form $this->createForm(OrderStatusType::class, $order);
  235.         $form->handleRequest($request);
  236.         if ($form->isSubmitted() && $form->isValid()) {
  237.             $this->getDoctrine()->getManager()->flush();
  238.             return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  239.         }
  240.         $orderedInvoices $invoiceRepo->getOrderedInvoices($order->getId());
  241.         $isInvoiceWithCancillation $this->isInvoiceWithCancillation($order->getInvoices());
  242.         return $this->render('order/show.html.twig', [
  243.             'order' => $order,
  244.             'form' => $form->createView(),
  245.             'isInvoiceWithCancillation' => $isInvoiceWithCancillation,
  246.             'orderedInvoices' => $orderedInvoices
  247.         ]);
  248.     }
  249.     /**
  250.      * @Route("/search/{occurrenceId}/{timeId}", name="order_search", methods="GET|POST", requirements={"id"="\d+"})
  251.      */
  252.     public function search(
  253.         Request $request,
  254.         Connection $connection,
  255.         CourseOccurrenceTimeRepository $timeRepository
  256.     ): Response {
  257.         $time $timeRepository->find($request->get('timeId'));
  258.         $sql 'SELECT
  259.             oi.*
  260.         FROM
  261.             customer_order_item oi,
  262.             course_occurrence o
  263.         WHERE
  264.             o.id = oi.course_occurrence_id AND
  265.             o.start = "' $time->getStart()->format('Y-m-d H:i:s') . '"
  266.         GROUP BY
  267.             oi._order_id';
  268.         $result $connection->fetchAssoc($sql);
  269.         if (empty($result)) {
  270.             $sql 'SELECT
  271.                 oi.*
  272.             FROM
  273.                 wait_item oi,
  274.                 course_occurrence o
  275.             WHERE
  276.                 o.id = oi.course_occurrence_id AND
  277.                 o.start = "' $time->getStart()->format('Y-m-d H:i:s') . '"
  278.             GROUP BY
  279.                 oi._order_id';
  280.             $result $connection->fetchAssoc($sql);
  281.         }
  282.         return $this->redirectToRoute('order_show', ['id' => $result['_order_id']]);
  283.     }
  284.     /**
  285.      * @Route("/{id}/edit/{return}", name="order_edit", methods="GET|POST", requirements={"id"="\d+","return"="\d+"})
  286.      */
  287.     public function edit(
  288.         Request $request,
  289.         Order $order,
  290.         $return '',
  291.         ConfigurationService $configService,
  292.         PersonRepository $personRepo
  293.     ): Response {
  294.         $isEmptyParticipants false;
  295.         $invoiceRecipient null;
  296.         $isInvoiceClosed false;
  297.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  298.         $customer null;
  299.         if ($order->getCustomer()) {
  300.             $customer $order->getCustomer();
  301.         }
  302.         if (
  303.             $order->getInvoices()->first() &&
  304.             $order->getInvoices()->first()->getStatus() == Invoice::STATUS_CLOSED
  305.         ) {
  306.             $isInvoiceClosed true;
  307.         }
  308.         if ($return) {
  309.             $customer $personRepo->find($return);
  310.             $invoiceRecipient $personRepo->getInvoiceReciepientMembers($return);
  311.             $invoiceRecipient $this->createInvoiceRecipientValues($invoiceRecipient$customer);
  312.             $customerChildrens $personRepo->getMembersByClient($customer);
  313.             $isEmptyParticipants = (empty($customerChildrens)) ? true false;
  314.         }
  315.         if ($order->getStatus() != Order::STATUS_PENDING) {
  316.             $this->addFlash('notice''Die Bestellung kann nur bearbeitet werden wenn Sie in Wartestellung ist.');
  317.             if ($return) {
  318.                 return $this->redirectToRoute('customer_orders', ['id' => $return]);
  319.             } else {
  320.                 return $this->redirectToRoute('order_index');
  321.             }
  322.         }
  323.         $form $this->createForm(OrderType::class, $order, [
  324.             'client' => $this->getCurrentClient(),
  325.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  326.             'invoiceRecipient' => $invoiceRecipient,
  327.             'customer' => $customer,
  328.             'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
  329.         ]);
  330.         $form->handleRequest($request);
  331.         if ($form->isSubmitted() && $form->isValid()) {
  332.             $this->updateParticipantsOfOrder($order);
  333.             $em $this->getDoctrine()->getManager();
  334.             foreach ($order->getOrderItems() as $item) {
  335.                 if (!$item->isFree() && $item->getCourseOccurrence()) {
  336.                     $item->setName($item->getCourseOccurrence()->getTitle());
  337.                     $em->persist($item);
  338.                 } else {
  339.                     $item->setCourseOccurrence(null);
  340.                     $em->persist($item);
  341.                 }
  342.             }
  343.             $em->flush();
  344.             $this->addFlash('notice''Die Bestellung wurde bearbeitet.');
  345.             return $this->redirectToRoute('order_index');
  346.             // }
  347.         }
  348.         return $this->render('order/edit.html.twig', [
  349.             'order' => $order,
  350.             'form' => $form->createView(),
  351.             'customer' => $customer,
  352.             'isEmptyParticipants' => $isEmptyParticipants,
  353.             'invoiceRecipient' => $invoiceRecipient,
  354.             'isInvoiceClosed' => $isInvoiceClosed
  355.         ]);
  356.     }
  357.     /**
  358.      * @Route("/{id}/cancel", name="order_cancel", methods="POST")
  359.      */
  360.     public function cancel(
  361.         Request $request,
  362.         Order $order,
  363.         ConfigurationService $configService,
  364.         OrderService $orderService
  365.     ): Response {
  366.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  367.         if ($this->isCsrfTokenValid('cancel' $order->getId(), $request->request->get('_token'))) {
  368.             $em $this->getDoctrine()->getManager();
  369.             // If order item is connected to time slot mark it bookable again
  370.             foreach ($order->getOrderItems() as $orderItem) {
  371.                 if ($time $orderItem->getCourseOccurrenceTime()) {
  372.                     $time->setAvailability('Bookable');
  373.                     $time->setOrderItem(null);
  374.                 }
  375.             }
  376.             foreach ($order->getWaitItems() as $waitItem) {
  377.                 if ($time $waitItem->getCourseOccurrenceTime()) {
  378.                     $time->setAvailability('Requestable');
  379.                     $time->setWaitItem(null);
  380.                 }
  381.             }
  382.             foreach ($order->getInvoices() as $invoice) {
  383.                 if (!$invoice->isCancelled() && !$invoice->isCancellation()) {
  384.                     $cancellation $orderService->createCancellation($invoice);
  385.                     $cancellation->setSignedBy($this->getCurrentUser());
  386.                     $invoice->setCancelled(true);
  387.                     $em->persist($cancellation);
  388.                 }
  389.             }
  390.             $order->setStatus(Order::STATUS_CANCELLED);
  391.             $orderService->calculateCancelOrderItems($order);
  392.             $em->flush();
  393.             $this->addFlash('notice''Bestellung storniert');
  394.         }
  395.         return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  396.     }
  397.     /**
  398.      * @Route("/set-cancel-date/{id}", name="participant_set-cancel-date")
  399.      */
  400.     public function setCancelDateForParticicpant(
  401.         Request $request,
  402.         OrderItemPerson $participant,
  403.         OrderService $orderService,
  404.         RequestStack $requestStack,
  405.         ManagerRegistry $managerRegistry,
  406.         LoggerInterface $logger
  407.     ): Response {
  408.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$participant->getOrderItem()->getOrder());
  409.         $form $this->createForm(OrderItemPersonCancelDate::class, null, [
  410.             'action' => $this->generateUrl('participant_set-cancel-date', ['id' => $participant->getId()])
  411.         ]);
  412.         $form->handleRequest($request);
  413.         $participant->setCancelled($orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant));
  414.         
  415.         if ($form->isSubmitted() && $form->isValid()) {
  416.             /**
  417.              * @var \DateTimeInterface $cancelDate
  418.              */
  419.             $cancelDate $form->getData()['cancelDate'];
  420.             // Kuendigungsdatum in entsprechenden Teilnehmereintrag im Kurs schreiben
  421.             $participant->setCancelled($cancelDate);
  422.             $em $managerRegistry->getManager();
  423.             $logger->debug("cancel date:" $cancelDate->format("d-m-Y H:i:s"));
  424.             $booking $participant->getOrderItem()->getCourseSubscriptionBooking();
  425.             if (!empty($booking)) {
  426.                 $terminationPeriod $booking->getCourseSubscription()->getTerminationPeriodMonths();
  427.                 $logger->debug($terminationPeriod);
  428.                 $diff $cancelDate->diff(new \DateTime());
  429.                 // if($diff->m < $terminationPeriod) {
  430.                     $cancellationTimestamp strtotime('+' $terminationPeriod ' months'$cancelDate->getTimeStamp());
  431.                 // } else {
  432.                 //    $cancellationTimestamp = $cancelDate->getTimestamp();
  433.                 //}
  434.                 $cancelDate->setTimestamp($cancellationTimestamp);
  435.                 $logger->debug($cancellationTimestamp);
  436.                 //dd($terminationPeriod, $cancellationTimestamp, $cancelDate);
  437.             }
  438.             $result $orderService->setCancelDateForParticipantInCourse(
  439.                 $this->getCurrentClient(),
  440.                 $participant,
  441.                 $cancelDate
  442.             );
  443.             //$logger->debug("TEST UND SO " . $oipWithCancelDate->getCancelled()->format("d-m-Y H:i:s"));
  444.             $em->flush();
  445.             // Aktive Eintraege/Bestellpositionen/Bestellungen fuer Kurstermine nach dem Kuendigungsdatum erhalten
  446.             $oipsToCancel $orderService->getAllActiveParticipationsAfterCancelDateByParticipant(
  447.                 $this->getCurrentClient(),
  448.                 $participant
  449.             );
  450.             $logger->debug("oipsToCancel: " json_encode($oipsToCancel));
  451.             // Diese Eintraege einzeln durchlaufen und stornieren
  452.             foreach ($oipsToCancel as $oipToCancel) {
  453.                 // Bei schon vorhandenen Rechnungen ggf. Storno-Rechnungen erstellen
  454.                 foreach ($oipToCancel->getOrderItem()->getOrder()->getInvoices() as $invoice) {
  455.                     if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($oipToCancel->getOrderItem())) {
  456.                         $cancellation $orderService->createCancellation($invoice$oipToCancel->getOrderItem(), $oipToCancel->getId());
  457.                         $cancellation->setSignedBy($this->getCurrentUser());
  458.                         $em->persist($cancellation);
  459.                     }
  460.                 }
  461.                 // Eintrag stornieren
  462.                 $orderService->cancelOrderItemParticipant($oipToCancel->getOrderItem(), $oipToCancel->getId());
  463.                 // Ggf. Bestellposition stornieren
  464.                 if (!$oipToCancel->getOrderItem()->hasUncancelledParticipants()) {
  465.                     $oipToCancel->getOrderItem()->setStatus(OrderItem::STATUS_CANCELLED);
  466.                     foreach ($oipToCancel->getOrderItem()->getMaterialCosts() as $materialCost) {
  467.                         $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
  468.                     }
  469.                 }
  470.                 // Ggf. Bestellung stornieren
  471.                 if (!$oipToCancel->getOrderItem()->getOrder()->hasUncancelledItems()) {
  472.                     $oipToCancel->getOrderItem()->getOrder()->setStatus(Order::STATUS_CANCELLED);
  473.                 }
  474.                 $orderService->calculateCancelOrderItem($oipToCancel->getOrderItem());
  475.             }
  476.             // Aenderungen in Datenbank speichern
  477.             $em->flush();
  478.             $flashExists false;
  479.             foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
  480.                 if ($flashType == 'notice' && $flashTitle == 'Kündigungsdatum eingetragen'$flashExists true;
  481.             }
  482.             if (!$flashExists$this->addFlash('notice''Kündigungsdatum eingetragen');
  483.             $route $request->headers->get('referer');
  484.             return $this->redirect($route);
  485.         }
  486.         return $this->render('course/_set-cancel-date.html.twig', [
  487.             'person' => $participant->getPerson(),
  488.             'form' => $form->createView(),
  489.             'cancelDate' => $participant->getCancelled(),
  490.             'today' => new \DateTime()
  491.         ]);
  492.     }
  493.     /**
  494.      * @Route("/{id}/cancel-item/{participantId}/{return}", name="order-item_cancel", methods="GET")
  495.      */
  496.     public function cancelItem(
  497.         Request $request,
  498.         OrderItem $orderItem,
  499.         int $participantId 0,
  500.         string $return '',
  501.         ConfigurationService $configService,
  502.         OrderService $orderService
  503.     ): Response {
  504.         $order $orderItem->getOrder();
  505.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  506.         $em $this->getDoctrine()->getManager();
  507.         foreach ($order->getInvoices() as $invoice) {
  508.             if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($orderItem)) {
  509.                 $cancellation $orderService->createCancellation($invoice$orderItem$participantId);
  510.                 $cancellation->setSignedBy($this->getCurrentUser());
  511.                 $em->persist($cancellation);
  512.             }
  513.         }
  514.         if ($participantId 0) {
  515.             $orderService->cancelOrderItemParticipant($orderItem$participantId);
  516.         } else {
  517.             $orderItem->cancelAllParticipants();
  518.         }
  519.         if (!$orderItem->hasUncancelledParticipants()) {
  520.             $orderItem->setStatus(OrderItem::STATUS_CANCELLED);
  521.             foreach ($orderItem->getMaterialCosts() as $materialCost) {
  522.                 $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
  523.             }
  524.         }
  525.         if (!$order->hasUncancelledItems()) {
  526.             $order->setStatus(Order::STATUS_CANCELLED);
  527.         }
  528.         $orderService->calculateCancelOrderItem($orderItem);
  529.         $em->flush();
  530.         $this->addFlash('notice''Kurs storniert');
  531.         // return $this->redirect(urldecode($return));
  532.         return $this->redirectToRoute('course_invoices', ['id' => $request->get('course_id')]);
  533.     }
  534.     /**
  535.      * @Route("/copy-participant/{id}", name="participant_copy-to-other-occurrence")
  536.      */
  537.     public function copyParticipantToOtherOccurrence(
  538.         Request $request,
  539.         OrderItemPerson $participant,
  540.         OrderService $orderService,
  541.         CourseOccurrenceRepository $coRepo,
  542.         RequestStack $requestStack
  543.     ): Response {
  544.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$participant->getOrderItem()->getOrder());
  545.         $selectableOccurrences $orderService->getAllOccurrencesOfCourseAParticipantIsNotInBeforeCancelDate($this->getCurrentClient(), $participant);
  546.         $selectableOccurrencesArray = [];
  547.         foreach ($selectableOccurrences as $selectableOccurrence) {
  548.             $selectableOccurrencesArray[$selectableOccurrence->getStart()->format('d.m.Y') . ' - ' $selectableOccurrence->getEnd()->format('d.m.Y')] = $selectableOccurrence->getId();
  549.         }
  550.         $form $this->createForm(OrderItemPersonCopy::class, null, [
  551.             'occurrences' => $selectableOccurrencesArray,
  552.             'action' => $this->generateUrl('participant_copy-to-other-occurrence', ['id' => $participant->getId()])
  553.         ]);
  554.         $form->handleRequest($request);
  555.         if ($form->isSubmitted() && $form->isValid()) {
  556.             $em $this->getDoctrine()->getManager();
  557.             $flashs = [];
  558.             $orders = [];
  559.             foreach ($form->getData()['occurrences'] as $occurrenceId) {
  560.                 $flash = [];
  561.                 $occurrence $coRepo->find($occurrenceId);
  562.                 $newOrder $orderService->generateOrderForCourseOccurrenceFromOrderItemPerson(
  563.                     $this->getCurrentClient(),
  564.                     $participant,
  565.                     $occurrence,
  566.                     $flash,
  567.                     false
  568.                 );
  569.                 if ($newOrder !== null) {
  570.                     $orders[] = $newOrder;
  571.                 }
  572.                 if (count($flash) > 0) {
  573.                     $flashs[] = $flash;
  574.                 }
  575.             }
  576.             foreach ($orders as $orderToSave) {
  577.                 $em->persist($orderToSave);
  578.             }
  579.             foreach ($flashs as $flashToShow) {
  580.                 foreach ($flashToShow as $key => $value) {
  581.                     $this->addFlash($key$value);
  582.                 }
  583.             }
  584.             // Aenderungen in Datenbank speichern
  585.             $em->flush();
  586.             $flashExists false;
  587.             foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
  588.                 if ($flashType == 'notice' && $flashTitle == 'Teilnehmer in ' count($orders) . ' weitere Termine übernommen'$flashExists true;
  589.             }
  590.             if (!$flashExists$this->addFlash('notice''Teilnehmer in ' count($orders) . ' weitere Termine übernommen');
  591.             return $this->redirectToRoute('course_participants', ['id' => $participant->getOrderItem()->getCourseOccurrence()->getCourse()->getId()]);
  592.         }
  593.         return $this->render('course/_copy-to-occurrence.html.twig', [
  594.             'person' => $participant->getPerson(),
  595.             'form' => $form->createView(),
  596.         ]);
  597.     }
  598.     /**
  599.      * @Route("/{id}/create-invoice", name="order_invoice_create", methods="GET")
  600.      */
  601.     public function createInvoice(
  602.         Request $request,
  603.         Order $order,
  604.         InvoiceService $invoiceService
  605.     ): Response {
  606.         $results $invoiceService->createInvoiceFromOrder($order);
  607.         $em $this->getDoctrine()->getManager();
  608.         //Update the order status
  609.         $newOrderState $order->setStatus(Order::STATUS_PROCESSING);
  610.         $em->persist($newOrderState);
  611.         foreach ($results['attendees'] as $attendee) {
  612.             $em->persist($attendee);
  613.         }
  614.         $em->persist($results['invoice']);
  615.         $em->flush();
  616.         $this->addFlash('notice'' Rechnung erstellt');
  617.         return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  618.     }
  619.     /**
  620.      * @Route("/{id}", name="order_delete", methods="DELETE")
  621.      */
  622.     public function delete(Request $requestOrder $order): Response
  623.     {
  624.         if ($this->isCsrfTokenValid('delete' $order->getId(), $request->request->get('_token'))) {
  625.             $em $this->getDoctrine()->getManager();
  626.             $em->remove($order);
  627.             $em->flush();
  628.         }
  629.         return $this->redirectToRoute('order_index');
  630.     }
  631.     protected function updateParticipantsOfOrder(Order $order)
  632.     {
  633.         if (count($order->getOrderItems()) > 0) {
  634.             foreach ($order->getOrderItems() as $orderItem) {
  635.                 if (count($orderItem->getParticipants()) > 0) {
  636.                     foreach ($orderItem->getParticipants() as $participant) {
  637.                         $participant->updateFieldsFromPerson();
  638.                     }
  639.                 }
  640.             }
  641.         }
  642.     }
  643.     private function createInvoiceRecipientValues($persons$customer)
  644.     {
  645.         $res[] = $customer;
  646.         foreach ($persons as $person) {
  647.             $res[] = $person;
  648.         }
  649.         return $res;
  650.     }
  651.     /**
  652.      * isInvoiceWithCancillation
  653.      *
  654.      * Checks whether one of the invoices is a cancellation invoice
  655.      *
  656.      * @param  Collection $invoices
  657.      * @return boolean
  658.      */
  659.     private function isInvoiceWithCancillation(Collection $invoices)
  660.     {
  661.         $cancelation false;
  662.         if (empty($invoices)) return $cancelation;
  663.         $counter count($invoices);
  664.         if ($counter || !($invoices[$counter 1]->isCancellation())) return $cancelation;
  665.         foreach ($invoices as $invoice) {
  666.             if ($invoice->isCancellation()) {
  667.                 $cancelation true;
  668.                 break;
  669.             }
  670.         }
  671.         return $cancelation;
  672.     }
  673.    /**
  674.      * @Route("/changestatus/{id}/{status}", name="change_status")
  675.      */
  676.     public function changeStatus(Order $order$status): Response 
  677.         $em $this->getDoctrine()->getManager();
  678.         $newstatus $order->setStatus($status);
  679.         $em->persist($newstatus);
  680.         $em->flush();
  681.         return $this->json([
  682.             'success' => 'Der Status wurde geändert.'
  683.         ]);
  684.     }
  685. }