src/Controller/OrderController.php line 186

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Order;
  4. use App\Entity\Person;
  5. use App\Entity\Invoice;
  6. use App\Form\OrderType;
  7. use App\Entity\WaitItem;
  8. use App\Entity\OrderItem;
  9. use App\Service\UiService;
  10. use App\Form\OrderStatusType;
  11. use App\Service\OrderService;
  12. use Doctrine\DBAL\Connection;
  13. use App\Service\MailerService;
  14. use App\Entity\OrderItemPerson;
  15. use App\Service\InvoiceService;
  16. use App\Entity\CourseOccurrence;
  17. use App\Form\OrderItemPersonCopy;
  18. use App\Repository\OrderRepository;
  19. use App\Repository\WaitItemRepository;
  20. use App\Service\EmailHistoryService;
  21. use App\Repository\PersonRepository;
  22. use App\Repository\InvoiceRepository;
  23. use App\Service\ConfigurationService;
  24. use App\Form\OrderItemPersonCancelDate;
  25. use App\Entity\CourseSubscriptionBooking;
  26. use Doctrine\Persistence\ManagerRegistry;
  27. use Doctrine\Common\Collections\Collection;
  28. use Psr\Log\LoggerInterface;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use App\Repository\OrderItemPersonRepository;
  31. use App\Repository\CourseOccurrenceRepository;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\Routing\Annotation\Route;
  34. use App\Repository\CourseOccurrenceTimeRepository;
  35. use Symfony\Component\HttpFoundation\RequestStack;
  36. use Menke\UserBundle\Controller\AbstractClientableController;
  37. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  38. use Menke\UserBundle\Entity\Client;
  39. /**
  40.  * @Route("/order")
  41.  * @IsGranted("ROLE_MANAGER")
  42.  */
  43. class OrderController extends AbstractClientableController
  44. {
  45.     const LISTING_LIMIT 25;
  46.     /**
  47.      * @Route("/", name="order_index", methods="GET")
  48.      */
  49.     public function index(
  50.         UiService $uiService,
  51.         OrderRepository $orderRepo,
  52.         OrderItemPersonRepository $orderItemPersonRepository,
  53.         Request $request,
  54.         RequestStack $requestStack
  55.     ): Response {
  56.         $order $uiService->getSortOrder('order-index-listing');
  57.         $em $this->getDoctrine()->getManager();
  58.         $filterOrders $request->get('orderAction');
  59.         if ($filterOrders) {
  60.             $requestStack->getSession()->set('orderFilter'$filterOrders);
  61.         } else {
  62.             $requestStack->getSession()->set('orderFilter''pending');
  63.         }
  64.         $dateareas $request->get('datearea');
  65.         if ($dateareas) {
  66.             $requestStack->getSession()->set('datearea'$dateareas);
  67.         }
  68. /*  Alle Member in den Orders und order item persons abgleichen und aktualisieren
  69.         $orderstest = $orderRepo->findAll();
  70.         foreach ($orderstest as $ordertest) {
  71.             if($ordertest->getCustomer() && $ordertest->getCustomer()->getMember()){
  72.             $ordertest->setCustomerMember($ordertest->getCustomer()->getMember());
  73.             $em->persist($ordertest);}
  74.         }
  75.         $entries = $orderItemPersonRepository->findAll();
  76.         foreach ($entries as $entry) {
  77.             // Hier wird der aktualisierte Member-Wert gesetzt
  78.             if($entry->getPerson() && $entry->getPerson()->getMember()){
  79.             $entry->setMember($entry->getPerson()->getMember());
  80.             $em->persist($entry);}
  81.         }
  82.   */     
  83.         $orders $orderRepo->getByClientPaged(
  84.             $this->getCurrentClient(),
  85.             self::LISTING_LIMIT,
  86.             $order['orderDirection'] ?? 'desc',
  87.             $order['orderBy'] ?? 'id',
  88.             1,
  89.             ($filterOrders) ? $filterOrders 'pending',
  90.             ($dateareas) ? $dateareas null,
  91.         );
  92.         return $this->render('order/index.html.twig', [
  93.             'uiService' => $uiService,
  94.             'orders' => $orders->getIterator(),
  95.             'total' => $orders->count(),
  96.             'pages' => ceil($orders->count() / self::LISTING_LIMIT),
  97.             'page' => 1,
  98.             'orderAction' => $request->get('orderAction'),
  99.             'datearea' => $request->get('datearea'),
  100.         ]);
  101.     }
  102.     /**
  103.      * @Route("/fast", name="order_index_fast", methods="GET")
  104.      */
  105.     public function indexfast(
  106.         UiService $uiService,
  107.         OrderRepository $orderRepo,
  108.         Request $request,
  109.         RequestStack $requestStack
  110.     ): Response {
  111.         $order $uiService->getSortOrder('order-index-listing');
  112.         $filterOrders $request->get('orderAction');
  113.         if ($filterOrders) {
  114.             $requestStack->getSession()->set('orderFilter'$filterOrders);
  115.         } else {
  116.             $requestStack->getSession()->set('orderFilter''pending');
  117.         }
  118.         $orders $orderRepo->getByClientPaged(
  119.             $this->getCurrentClient(),
  120.             self::LISTING_LIMIT,
  121.             $order['orderDirection'] ?? 'desc',
  122.             $order['orderBy'] ?? 'date',
  123.             1,
  124.             ($filterOrders) ? $filterOrders ''
  125.         );
  126.         return $this->render('order/fastindex.html.twig', [
  127.             'uiService' => $uiService,
  128.             'orders' => $orders->getIterator(),
  129.             'total' => $orders->count(),
  130.             'pages' => ceil($orders->count() / self::LISTING_LIMIT),
  131.             'page' => 1,
  132.             'orderAction' => $request->get('orderAction'),
  133.         ]);
  134.     }
  135.     /**
  136.      * @Route("/{page}/{orderby}/{order}", name="order_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
  137.      */
  138.     public function indexListing(
  139.         OrderRepository $orderRepo,
  140.         UiService $uiService,
  141.         $page,
  142.         $orderby,
  143.         $order,
  144.         Request $request,
  145.         RequestStack $requestStack,
  146.     ): Response {
  147.         $uiService->storeSortOrder('order-index-listing'$orderby$order);
  148.         $orders $orderRepo->getByClientPaged(
  149.             $this->getCurrentClient(),
  150.             self::LISTING_LIMIT,
  151.             $order,
  152.             $orderby,
  153.             $page,
  154.             $requestStack->getSession()->get('orderFilter')
  155.         );
  156.         return $this->render('order/_index_listing.html.twig', [
  157.             'uiService' => $uiService,
  158.             'orders' => $orders->getIterator(),
  159.             'total' => $orders->count(),
  160.             'pages' => ceil($orders->count() / self::LISTING_LIMIT),
  161.             'page' => $page,
  162.         ]);
  163.     }
  164.     /**
  165.      * @Route("/new/{return}", name="order_new", methods="GET|POST")
  166.      */
  167.     public function new(
  168.         Request $request,
  169.         $return null,
  170.         PersonRepository $personRepo,
  171.         ConfigurationService $configService,
  172.         OrderService $orderService
  173.     ): Response {
  174.         $customer null;
  175.         $invoiceRecipient null;
  176.         $isEmptyParticipants false;
  177.         if ($return) {
  178.             $customer $personRepo->find($return);
  179.             $invoiceRecipient $personRepo->getInvoiceReciepientMembers($return);
  180.             $invoiceRecipient $this->createInvoiceRecipientValues($invoiceRecipient$customer);
  181.             $customerChildrens $personRepo->getMembersByClient($customer);
  182.             $isEmptyParticipants = (empty($customerChildrens)) ? true false;
  183.         }
  184.         $em $this->getDoctrine()->getManager();
  185.         $order = new Order();
  186.         $order->setDate(new \DateTime());
  187.         $order->setStatus(Order::STATUS_PENDING);
  188.         $order->setNumber($configService->getNewOrderNumberByClient($this->getCurrentClient()));
  189.         $order->setClient($this->getCurrentClient());
  190.         $order->setCustomer($customer);
  191.         $order->setCustomerData($customer);
  192.         $order->setCreated(new \DateTime());
  193.         $order->setPerson($customer);
  194.         $form $this->createForm(OrderType::class, $order, [
  195.             'client' => $this->getCurrentClient(),
  196.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  197.             'customer' => $customer,
  198.             'invoiceRecipient' => $invoiceRecipient,
  199.             'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
  200.         ]);
  201.         $form->handleRequest($request);
  202.         //   $em->persist($order);
  203.         // Check if creation is possible
  204.         if ($form->isSubmitted() && $form->isValid()) {
  205.             if (!$order->checkCustomerData($customer)) {
  206.                 $this->addFlash('error''Die Kundendaten sind unvollständig. Es kann keine neue Bestellung angelegt werden.');
  207.                 if ($return) {
  208.                     return $this->redirectToRoute('customer_orders', ['id' => $return]);
  209.                 } else {
  210.                     return $this->redirectToRoute('order_index');
  211.                 }
  212.             }
  213.             foreach ($order->getOrderItems() as $orderItem) {
  214.                 if ($orderItem->getCourseOccurrence()) {
  215.                     $orderItem->setCourseOccurrence($orderItem->getCourseOccurrence());
  216.                     if ($orderItem->getCourseOccurrence()->getCourse()->getMaterialCost() > 0) {
  217.                         $item = new OrderItem();
  218.                         $item->setCourseOccurrence($orderItem->getCourseOccurrence());
  219.                         $item->setPrice($orderItem->getCourseOccurrence()->getCourse()->getMaterialCost());
  220.                         $item->setTaxRate($orderItem->getCourseOccurrence()->getCourse()->getTaxRate());
  221.                         $item->setQuantity($orderItem->getQuantity());
  222.                         // $item->setCourseItem($orderItem->getCourseOccurrence()->getCourse());
  223.                          $item->setCourseItem($orderItem);
  224.                         $item->setIsFree(false);
  225.                         $item->setOrder($order);
  226.                         $item->setCreated(new \Datetime());
  227.                         // $item->setCourseItem($orderItem);
  228.                         $em->persist($item);
  229.                     }
  230.                     $em->persist($orderItem);
  231.                 }
  232.                 // Skip participants check for free items
  233.                 if ($orderItem->getCourseOccurrence() === null) {
  234.                     continue;
  235.                 }
  236.                 // Check if order item has at least one participant
  237.                 if (count($orderItem->getParticipants()) == 0) {
  238.                     $this->addFlash('error''Der Kurs enthält keine Teilnehmer.');
  239.                     return $this->redirectToRoute('order_new', ['return' => $return]);
  240.                 }
  241.             }
  242.             $allItemsBookable true;
  243.             // $em->flush();
  244.             foreach ($order->getOrderItems() as $orderItem) {
  245.                 $orderItem->setCourseOccurrence($orderItem->getCourseOccurrence());
  246.                 $orderItem->setCreated(new \DateTime());
  247.                 if ($orderItem->getCourse()) {
  248.                     $orderItem->setName($orderItem->getCourse()->getTitle());
  249.                     $orderItem->setDescription($orderItem->getCourse()->getSubtitle());
  250.                 } else {
  251.                     $orderItem->setName($orderItem->getName());
  252.                     $orderItem->setDescription($orderItem->getDescription());
  253.                 }
  254.                 //    $em->persist($orderItem);
  255.                 //    $em->flush($orderItem);
  256.                 if ($orderItem->getCourseOccurrence()) {
  257.                     $occurrence $orderItem->getCourseOccurrence();
  258.                     ///// testen und abgleichen was in der Datenbank steht und wie viele Buchungen es wirklich gibt ////
  259.                     //  $occurrence->setBookedSlots($occurrence->getBookedSlots());
  260.                     //    $em->persist($occurrence);
  261.                     //    $em->flush($occurrence);
  262.                     if (($occurrence->getSlots() < ($orderItem->getQuantity() + $occurrence->getBookedSlots())) && $occurrence->getReservationAllowed()) {
  263.                         $waitItem WaitItem::fromOrderItem($orderItem);
  264.                         $waitItem->setCreated(new \DateTime());
  265.                         $em->persist($waitItem);
  266.                         foreach ($orderItem->getParticipants() as $participant) {
  267.                             $participant->setOrderItem(null);
  268.                             $participant->setTitle($participant->getPerson()->getTitle());
  269.                             $participant->setSalutation($participant->getPerson()->getSalutation());
  270.                             $participant->setMember($participant->getPerson()->getMember());
  271.                             $participant->setFirstname($participant->getPerson()->getFirstname());
  272.                             $participant->setLastname($participant->getPerson()->getLastname());
  273.                             $participant->setDateOfBirth($participant->getPerson()->getDateOfBirth());
  274.                             $participant->setComment($participant->getPerson()->getComment());
  275.                             $participant->setOrderItem($orderItem);
  276.                             $participant->setCreated(new \DateTime());
  277.                             // $orderItem->removeParticipant($participant);
  278.                             //$orderItem->setQuantity($orderItem->getQuantity() - 1);
  279.                             $em->persist($participant);
  280.                         }
  281.                         $order->addWaitItem($waitItem);
  282.                         $this->addFlash('error''Im Kurs "' $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar. Es fehlen "' . ($orderItem->getQuantity() + $occurrence->getBookedSlots()) - $occurrence->getSlots() . '" Plätze. Die komplette Buchung wurde stattdessen zur Warteliste hinzugefügt.');
  283.                         $em->flush();
  284.                         // $order->removeOrderItem($orderItem);
  285.                         $orderItem->setOrder(null);
  286.                         $orderItem->setStatus('wait_item');
  287.                         //$orderItem->setCancelledQuantity($orderItem->getQuantity());
  288.                         //   $orderItem->setQuantity($orderItem->getQuantity());
  289.                         $em->persist($orderItem);
  290.                         $em->persist($order);
  291.                         //$em->remove($orderItem);
  292.                         $em->flush();
  293.                         //  var_dump($orderItem->getOrder());
  294.                         return $this->redirectToRoute('customer_orders', ['id' => $return]);
  295.                     } elseif (($occurrence->getSlots() < ($orderItem->getQuantity() + $occurrence->getBookedSlots())) && !$occurrence->getReservationAllowed()) {
  296.                         //  $occurrence->setBookedSlots($occurrence->getBookedSlots());
  297.                         $em->persist($occurrence);
  298.                         $em->remove($order);
  299.                         $em->flush();
  300.                         $allItemsBookable false;
  301.                         $this->addFlash('error''Im Kurs "' $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar. Es fehlen "' . ($orderItem->getQuantity() + $occurrence->getBookedSlots()) - $occurrence->getSlots() . '" Plätze.');
  302.                         return $this->redirectToRoute('customer_orders', ['id' => $return]);
  303.                     } else {
  304.                         if ($orderItem->getCourseOccurrence()->getCourse()->getCourseNature() == 'CourseSubscription') {
  305.                             $this->addFlash('warning''courseSubsciption');
  306.                             //    $courseSubscriptionBooking = new CourseSubscriptionBooking($orderItem, $orderItem->getCourse());
  307.                             //    $courseSubscriptionBooking->setOrderItem($orderItem);
  308.                             //    $courseSubscriptionBooking->setCourse($orderItem->getCourseOccurrence()->getCourse());
  309.                             //    $courseSubscriptionBooking->setCourseSubscription($orderItem->getCourseOccurrence()->getCourse()->getSubscription());
  310.                             //    $orderItem->setCourseSubscriptionBooking($courseSubscriptionBooking);
  311.                             //    $em->persist($courseSubscriptionBooking);
  312.                         }
  313.                         /*
  314.                         foreach ($orderItem->getParticipants() as $participant) 
  315.                         { 
  316.                             $occurrence->setBookedSlots($occurrence->getBookedSlots() + 1);
  317.                         }
  318.                         $em->persist($occurrence);
  319.                         */
  320.                         // $em->persist($occurrence);
  321.                         //            $occurrence = $orderItem->getCourseOccurrence();
  322.                         //  $occurrence->setBookedSlots($occurrence->getBookedSlotsDirectly() + $orderItem->getQuantity());
  323.                         //  $occurrence->setBookedSlots($occurrence->getBookedSlots() + $orderItem->getQuantity());
  324.                         //            $em->persist($occurrence);
  325.                         //     $em->flush();
  326.                         //   $occurrences[] = $occurrence;
  327.                     }
  328.                 }
  329.                 //  $em->flush();
  330.             }
  331.             $this->updateParticipantsOfOrder($order);
  332.             if ($orderItem->getCourse()) {
  333.                 $occurrence->setBookedSlots($occurrence->getBookedSlots() + $orderItem->getQuantity());
  334.             }
  335.             //  $em->flush();
  336.             if ($allItemsBookable) {
  337.                 if (count($order->getOrderItems()) > ||  count($order->getWaitItems()) > 0) {
  338.                     $order->setClient($this->getCurrentClient());
  339.                     $order->setCustomer($customer);
  340.                     $order->setCustomerData($customer);
  341.                     if ($customer->getIban()) {
  342.                         $order->setPaymentType(Order::PAYMENT_DEBIT);
  343.                         $order->setIban(
  344.                             strtoupper(
  345.                             preg_replace('/\s+/'''$customer->getIban())
  346.                                        )
  347.                                );
  348.                         $order->setBic($customer->getBic());
  349.                         $order->setBank($customer->getBank());
  350.                     }
  351.                     $orderItem->setOrder($order);
  352.                     $orderItem->getCourseOccurrence();
  353.                     // Ggf. nachfolgende Bestellungen fuer Abokurse generieren und speichern
  354.                     $flashs = [];
  355.                     $followingOrders $orderService->generateOrdersForSubscriptionCoursesAllFollowingOccurrences($this->getCurrentClient(), $order$flashs);
  356.                     foreach ($followingOrders as $orderToSave) {
  357.                         $em->persist($orderToSave);
  358.                     }
  359.                     foreach ($flashs as $flashToShow) {
  360.                         foreach ($flashToShow as $key => $value) {
  361.                             $this->addFlash($key$value);
  362.                         }
  363.                     }
  364.                 }
  365.                 /*
  366.                 foreach ($order->getOrderItems() as $orderItem) {
  367.                     if ($orderItem->getMaterialCosts()) {
  368.                                    $item = new OrderItem();
  369.                                    $item->setCourseOccurrence($orderItem->getCourseOccurrence());
  370.                                    $item->setPrice($orderItem->getCourseOccurrence()->getCourse()->getMaterialCost());
  371.                                    $item->setTaxRate($orderItem->getCourseOccurrence()->getCourse()->getTaxRate());
  372.                                    $item->setQuantity(1);
  373.                                    $item->setIsFree(false);
  374.                                    $item->setOrder($order);
  375.                                    $item->setCourseItem($orderItem);
  376.                                    $item->setCreated(new \Datetime());
  377.                        }
  378.                        $em->persist($item);
  379.                    }
  380.                    */
  381.                 $em->persist($order);
  382.                 $em->flush();
  383.                 if ($return) {
  384.                     if ($orderItem->getCourse()) {
  385.                         $this->addFlash('warning''Der Kurs "' $occurrence->getTitle() . '" wurde mit ' $orderItem->getQuantity() . ' Plätzen bebucht');
  386.                     }
  387.                     return $this->redirectToRoute('customer_orders', ['id' => $return]);
  388.                 } else {
  389.                     return $this->redirectToRoute('order_index');
  390.                 }
  391.             }
  392.             $em->remove($orderItem);
  393.             $em->remove($order);
  394.             $em->flush();
  395.             $this->addFlash('warning''LETZTE MÖGLICHKEIT "' $occurrence->getTitle() . '" ' $occurrence->getSlots() . ' | ' $occurrence->getBookedSlots() . '|' . ($occurrence->getSlots() - $occurrence->getBookedSlots()) . ' | ' $orderItem->getQuantity());
  396.         }
  397.         return $this->render('order/new.html.twig', [
  398.             'order' => $order,
  399.             'form' => $form->createView(),
  400.             'customer' => $customer,
  401.             'invoiceRecipient' => $invoiceRecipient,
  402.             'invalidCustomerData' => !$order->checkCustomerData($customer),
  403.             'isEmptyParticipants' => $isEmptyParticipants,
  404.             'isInvoiceClosed' => false
  405.         ]);
  406.     }
  407.     /**
  408.      * @Route("/{id}", name="order_show", methods="GET|POST", requirements={"id"="\d+"})
  409.      */
  410.     public function show(
  411.         Request $request,
  412.         Order $order,
  413.         InvoiceRepository $invoiceRepo
  414.     ): Response {
  415.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  416.         $form $this->createForm(OrderStatusType::class, $order);
  417.         $form->handleRequest($request);
  418.         if ($form->isSubmitted() && $form->isValid()) {
  419.             $this->getDoctrine()->getManager()->flush();
  420.             return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  421.         }
  422.       
  423.         $orderedInvoices $invoiceRepo->getOrderedInvoices($order->getId());
  424.         $isInvoiceWithCancillation $this->isInvoiceWithCancillation($order->getInvoices());
  425.         return $this->render('order/show.html.twig', [
  426.             'order' => $order,
  427.             'form' => $form->createView(),
  428.             'isInvoiceWithCancillation' => $isInvoiceWithCancillation,
  429.             'orderedInvoices' => $orderedInvoices
  430.         ]);
  431.     }
  432.     /**
  433.      * @Route("/search/{occurrenceId}/{timeId}", name="order_search", methods="GET|POST", requirements={"id"="\d+"})
  434.      */
  435.     public function search(
  436.         Request $request,
  437.         Connection $connection,
  438.         CourseOccurrenceTimeRepository $timeRepository
  439.     ): Response {
  440.         $time $timeRepository->find($request->get('timeId'));
  441.         $sql 'SELECT
  442.             oi.*
  443.         FROM
  444.             customer_order_item oi,
  445.             course_occurrence o
  446.         WHERE
  447.             o.id = oi.course_occurrence_id AND
  448.             o.start = "' $time->getStart()->format('Y-m-d H:i:s') . '"
  449.         GROUP BY
  450.             oi._order_id';
  451.         $result $connection->fetchAssoc($sql);
  452.         if (empty($result)) {
  453.             $sql 'SELECT
  454.                 oi.*
  455.             FROM
  456.                 wait_item oi,
  457.                 course_occurrence o
  458.             WHERE
  459.                 o.id = oi.course_occurrence_id AND
  460.                 o.start = "' $time->getStart()->format('Y-m-d H:i:s') . '"
  461.             GROUP BY
  462.                 oi._order_id';
  463.             $result $connection->fetchAssoc($sql);
  464.         }
  465.         return $this->redirectToRoute('order_show', ['id' => $result['_order_id']]);
  466.     }
  467.     /**
  468.      * @Route("/{id}/edit/{return}", name="order_edit", methods="GET|POST", requirements={"id"="\d+","return"="\d+"})
  469.      */
  470.     public function edit(
  471.         Request $request,
  472.         Order $order,
  473.         $return '',
  474.         ConfigurationService $configService,
  475.         PersonRepository $personRepo
  476.     ): Response {
  477.         $isEmptyParticipants false;
  478.         $invoiceRecipient null;
  479.         $isInvoiceClosed false;
  480.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  481.         $order->setModified(new \DateTime());
  482.         $customer null;
  483.         if ($order->getCustomer()) {
  484.             $customer $order->getCustomer();
  485.         }
  486.         if (
  487.             $order->getInvoices()->first() &&
  488.             $order->getInvoices()->first()->getStatus() == Invoice::STATUS_CLOSED
  489.         ) {
  490.             $isInvoiceClosed true;
  491.         }
  492.         if ($return) {
  493.             $customer $personRepo->find($return);
  494.             $invoiceRecipient $personRepo->getInvoiceReciepientMembers($return);
  495.             $invoiceRecipient $this->createInvoiceRecipientValues($invoiceRecipient$customer);
  496.             $customerChildrens $personRepo->getMembersByClient($customer);
  497.             $isEmptyParticipants = (empty($customerChildrens)) ? true false;
  498.         }
  499.         if ($order->getStatus() != Order::STATUS_PENDING) {
  500.             $this->addFlash('notice''Die Bestellung kann nur bearbeitet werden wenn Sie in Wartestellung ist.');
  501.             if ($return) {
  502.                 return $this->redirectToRoute('customer_orders', ['id' => $return]);
  503.             } else {
  504.                 return $this->redirectToRoute('order_index');
  505.             }
  506.         }
  507.         $form $this->createForm(OrderType::class, $order, [
  508.             'client' => $this->getCurrentClient(),
  509.             'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
  510.             'invoiceRecipient' => $invoiceRecipient,
  511.             'customer' => $customer,
  512.             'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
  513.         ]);
  514.         $form->handleRequest($request);
  515.         if ($form->isSubmitted() && $form->isValid()) {
  516.             $this->updateParticipantsOfOrder($order);
  517.             $em $this->getDoctrine()->getManager();
  518.             foreach ($order->getOrderItems() as $item) {
  519.                 $item->setModified(new \DateTime());
  520.                 if (!$item->isFree() && $item->getCourseOccurrence()) {
  521.                     $item->setName($item->getCourseOccurrence()->getTitle());
  522.                     $em->persist($item);
  523.                 } else {
  524.                     $item->setCourseOccurrence(null);
  525.                     $em->persist($item);
  526.                 }
  527.             }
  528.             $em->flush();
  529.             $this->addFlash('notice''Die Bestellung wurde bearbeitet.');
  530.             return $this->redirectToRoute('order_index');
  531.             // }
  532.         }
  533.         return $this->render('order/edit.html.twig', [
  534.             'order' => $order,
  535.             'form' => $form->createView(),
  536.             'customer' => $customer,
  537.             'isEmptyParticipants' => $isEmptyParticipants,
  538.             'invoiceRecipient' => $invoiceRecipient,
  539.             'isInvoiceClosed' => $isInvoiceClosed
  540.         ]);
  541.     }
  542.     /**
  543.      * @Route("/{id}/cancel", name="order_cancel", methods="POST")
  544.      */
  545.     public function cancel(
  546.         Request $request,
  547.         Order $order,
  548.         ConfigurationService $configService,
  549.         OrderService $orderService
  550.     ): Response {
  551.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  552.         if ($this->isCsrfTokenValid('cancel' $order->getId(), $request->request->get('_token'))) {
  553.             $em $this->getDoctrine()->getManager();
  554.             foreach ($order->getOrderItems() as $orderItem) {
  555.                 // If order item is connected to time slot mark it bookable again
  556.                 if ($time $orderItem->getCourseOccurrenceTime()) {
  557.                     $time->setAvailability('Bookable');
  558.                     $time->setOrderItem(null);
  559.                 }
  560.                 if ($orderItem) {
  561.                     $orderItem->setStatus('cancelled');
  562.                     foreach ($orderItem->getParticipants() as $person) {
  563.                         $person->setStatus('cancelled');
  564.                         $person->setCancelled(new \DateTime());
  565.                         $person->setModified(new \DateTime());
  566.                         $em->persist($person);
  567.                     }
  568.                     $orderItem->setCancelledQuantity($orderItem->getCancelledQuantity() + 1);
  569.                     $orderItem->setQuantity($orderItem->getQuantity() - 1);
  570.                     $orderItem->setModified(new \DateTime());
  571.                     //$orderItem->setQuantity('0');
  572.                 }
  573.             }
  574.             foreach ($order->getWaitItems() as $waitItem) {
  575.                 if ($time $waitItem->getCourseOccurrenceTime()) {
  576.                     $time->setAvailability('Requestable');
  577.                     $time->setWaitItem(null);
  578.                 }
  579.             }
  580.             foreach ($order->getInvoices() as $invoice) {
  581.                 if (!$invoice->isCancelled() && !$invoice->isCancellation()) {
  582.                     $cancellation $orderService->createCancellation($invoice);
  583.                     $cancellation->setSignedBy($this->getCurrentUser());
  584.                     $invoice->setCancelled(true);
  585.                     $em->persist($cancellation);
  586.                 }
  587.             }
  588.             $order->setStatus(Order::STATUS_CANCELLED);
  589.             $order->setModified(new \DateTime());
  590.             $orderService->calculateCancelOrderItems($order);
  591.             $em->flush();
  592.             $this->addFlash('notice''Bestellung storniert');
  593.         }
  594.         return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  595.     }
  596.     /**
  597.      * @Route("/set-cancel-date/{id}", name="participant_set-cancel-date")
  598.      */
  599.     public function setCancelDateForParticicpant(
  600.         Request $request,
  601.         OrderItemPerson $participant,
  602.         OrderService $orderService,
  603.         RequestStack $requestStack,
  604.         ManagerRegistry $managerRegistry,
  605.         //  LoggerInterface $logger
  606.     ): Response {
  607.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$participant->getOrderItem()->getOrder());
  608.         $form $this->createForm(OrderItemPersonCancelDate::class, null, [
  609.             'action' => $this->generateUrl('participant_set-cancel-date', ['id' => $participant->getId()])
  610.         ]);
  611.         $form->handleRequest($request);
  612.         $participant->setCancelled($orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant));
  613.         if ($form->isSubmitted() && $form->isValid()) {
  614.             /**
  615.              * @var \DateTimeInterface $cancelDate
  616.              */
  617.             $cancelDate $form->getData()['cancelDate'];
  618.             // Kuendigungsdatum in entsprechenden Teilnehmereintrag im Kurs schreiben
  619.             $participant->setCancelled($cancelDate);
  620.             $em $managerRegistry->getManager();
  621.             $booking $participant->getOrderItem()->getCourseSubscriptionBooking();
  622.             if (!empty($booking)) {
  623.                 $terminationPeriod $booking->getCourseSubscription()->getTerminationPeriodMonths();
  624.                 $cancellationTimestamp strtotime('+' $terminationPeriod ' months'$cancelDate->getTimeStamp());
  625.                 $cancelDate->setTimestamp($cancellationTimestamp);
  626.             }
  627.             $result $orderService->setCancelDateForParticipantInCourse(
  628.                 $this->getCurrentClient(),
  629.                 $participant,
  630.                 $cancelDate
  631.             );
  632.             $em->flush();
  633.             // Aktive Eintraege/Bestellpositionen/Bestellungen fuer Kurstermine nach dem Kuendigungsdatum erhalten
  634.             $oipsToCancel $orderService->getAllActiveParticipationsAfterCancelDateByParticipant(
  635.                 $this->getCurrentClient(),
  636.                 $participant
  637.             );
  638.             // Diese Eintraege einzeln durchlaufen und stornieren
  639.             foreach ($oipsToCancel as $oipToCancel) {
  640.                 // Bei schon vorhandenen Rechnungen ggf. Storno-Rechnungen erstellen
  641.                 foreach ($oipToCancel->getOrderItem()->getOrder()->getInvoices() as $invoice) {
  642.                     if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($oipToCancel->getOrderItem())) {
  643.                         $cancellation $orderService->createCancellation($invoice$oipToCancel->getOrderItem(), $oipToCancel->getId());
  644.                         $cancellation->setSignedBy($this->getCurrentUser());
  645.                         $em->persist($cancellation);
  646.                     }
  647.                 }
  648.                 // Eintrag stornieren
  649.                 $orderService->cancelOrderItemParticipant($oipToCancel->getOrderItem(), $oipToCancel->getId());
  650.                 // Ggf. Bestellposition stornieren
  651.                 if (!$oipToCancel->getOrderItem()->hasUncancelledParticipants()) {
  652.                     $oipToCancel->getOrderItem()->setStatus(OrderItem::STATUS_CANCELLED);
  653.                     foreach ($oipToCancel->getOrderItem()->getMaterialCosts() as $materialCost) {
  654.                         $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
  655.                     }
  656.                 }
  657.                 // Ggf. Bestellung stornieren
  658.                 if (!$oipToCancel->getOrderItem()->getOrder()->hasUncancelledItems()) {
  659.                     $oipToCancel->getOrderItem()->getOrder()->setStatus(Order::STATUS_CANCELLED);
  660.                 }
  661.                 $orderService->calculateCancelOrderItem($oipToCancel->getOrderItem());
  662.             }
  663.             // Aenderungen in Datenbank speichern
  664.             $em->flush();
  665.             $flashExists false;
  666.             foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
  667.                 if ($flashType == 'notice' && $flashTitle == 'Kündigungsdatum eingetragen'$flashExists true;
  668.             }
  669.             if (!$flashExists$this->addFlash('notice''Kündigungsdatum eingetragen');
  670.             $route $request->headers->get('referer');
  671.             return $this->redirect($route);
  672.         }
  673.         return $this->render('course/_set-cancel-date.html.twig', [
  674.             'person' => $participant->getPerson(),
  675.             'form' => $form->createView(),
  676.             'cancelDate' => $participant->getCancelled(),
  677.             'today' => new \DateTime()
  678.         ]);
  679.     }
  680.     /**
  681.      * @Route("/{id}/cancel-item/{participantId}/{return}", name="order-item_cancel", methods="GET")
  682.      */
  683.     public function cancelItem(
  684.         Request $request,
  685.         OrderItem $orderItem,
  686.         int $participantId 0,
  687.         string $return '',
  688.         ConfigurationService $configService,
  689.         OrderService $orderService
  690.     ): Response {
  691.         $order $orderItem->getOrder();
  692.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$order);
  693.         $em $this->getDoctrine()->getManager();
  694.         foreach ($order->getInvoices() as $invoice) {
  695.             if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($orderItem)) {
  696.                 $cancellation $orderService->createCancellation($invoice$orderItem$participantId);
  697.                 $cancellation->setSignedBy($this->getCurrentUser());
  698.                 $em->persist($cancellation);
  699.             }
  700.         }
  701.         if ($participantId 0) {
  702.             $orderService->cancelOrderItemParticipant($orderItem$participantId);
  703.         } else {
  704.             $orderItem->cancelAllParticipants();
  705.         }
  706.         if (!$orderItem->hasUncancelledParticipants()) {
  707.             $orderItem->setStatus(OrderItem::STATUS_CANCELLED);
  708.             foreach ($orderItem->getMaterialCosts() as $materialCost) {
  709.                 $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
  710.             }
  711.         }
  712.         if (!$order->hasUncancelledItems()) {
  713.             $order->setStatus(Order::STATUS_CANCELLED);
  714.         }
  715.         $orderService->calculateCancelOrderItem($orderItem);
  716.         $orderItem->setModified(new \DateTime());
  717.         $order->setModified(new \DateTime());
  718.         $em->flush();
  719.         $this->addFlash('notice''Kurs storniert');
  720.         // return $this->redirect(urldecode($return));
  721.         return $this->redirectToRoute('course_invoices', ['id' => $request->get('course_id')]);
  722.     }
  723.     /**
  724.      * @Route("/copy-participant/{id}", name="participant_copy-to-other-occurrence")
  725.      */
  726.     public function copyParticipantToOtherOccurrence(
  727.         Request $request,
  728.         OrderItemPerson $participant,
  729.         OrderService $orderService,
  730.         CourseOccurrenceRepository $coRepo,
  731.         RequestStack $requestStack
  732.     ): Response {
  733.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$participant->getOrderItem()->getOrder());
  734.         $selectableOccurrences $orderService->getAllOccurrencesOfCourseAParticipantIsNotInBeforeCancelDate($this->getCurrentClient(), $participant);
  735.         $selectableOccurrencesArray = [];
  736.         foreach ($selectableOccurrences as $selectableOccurrence) {
  737.             $selectableOccurrencesArray[$selectableOccurrence->getStart()->format('d.m.Y') . ' - ' $selectableOccurrence->getEnd()->format('d.m.Y')] = $selectableOccurrence->getId();
  738.         }
  739.         $form $this->createForm(OrderItemPersonCopy::class, null, [
  740.             'occurrences' => $selectableOccurrencesArray,
  741.             'action' => $this->generateUrl('participant_copy-to-other-occurrence', ['id' => $participant->getId()])
  742.         ]);
  743.         $form->handleRequest($request);
  744.         if ($form->isSubmitted() && $form->isValid()) {
  745.             $em $this->getDoctrine()->getManager();
  746.             $flashs = [];
  747.             $orders = [];
  748.             foreach ($form->getData()['occurrences'] as $occurrenceId) {
  749.                 $flash = [];
  750.                 $occurrence $coRepo->find($occurrenceId);
  751.                 $newOrder $orderService->generateOrderForCourseOccurrenceFromOrderItemPerson(
  752.                     $this->getCurrentClient(),
  753.                     $participant,
  754.                     $occurrence,
  755.                     $flash,
  756.                     false
  757.                 );
  758.                 if ($newOrder !== null) {
  759.                     $orders[] = $newOrder;
  760.                 }
  761.                 if (count($flash) > 0) {
  762.                     $flashs[] = $flash;
  763.                 }
  764.             }
  765.             foreach ($orders as $orderToSave) {
  766.                 $em->persist($orderToSave);
  767.             }
  768.             foreach ($flashs as $flashToShow) {
  769.                 foreach ($flashToShow as $key => $value) {
  770.                     $this->addFlash($key$value);
  771.                 }
  772.             }
  773.             // Aenderungen in Datenbank speichern
  774.             $em->flush();
  775.             $flashExists false;
  776.             foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
  777.                 if ($flashType == 'notice' && $flashTitle == 'Teilnehmer in ' count($orders) . ' weitere Termine übernommen'$flashExists true;
  778.             }
  779.             if (!$flashExists$this->addFlash('notice''Teilnehmer in ' count($orders) . ' weitere Termine übernommen');
  780.             return $this->redirectToRoute('course_participants', ['id' => $participant->getOrderItem()->getCourseOccurrence()->getCourse()->getId()]);
  781.         }
  782.         return $this->render('course/_copy-to-occurrence.html.twig', [
  783.             'person' => $participant->getPerson(),
  784.             'form' => $form->createView(),
  785.         ]);
  786.     }
  787.     /**
  788.      * @Route("/{id}/create-invoice", name="order_invoice_create", methods="GET")
  789.      */
  790.     public function createInvoice(
  791.         Request $request,
  792.         Order $order,
  793.         InvoiceService $invoiceService
  794.     ): Response {
  795.         $results $invoiceService->createInvoiceFromOrder($order);
  796.         $em $this->getDoctrine()->getManager();
  797.         //Update the order status
  798.         $newOrderState $order->setStatus(Order::STATUS_PROCESSING);
  799.         $em->persist($newOrderState);
  800.         foreach ($results['attendees'] as $attendee) {
  801.             $em->persist($attendee);
  802.         }
  803.         $em->persist($results['invoice']);
  804.         $em->flush();
  805.         $this->addFlash('notice'' Rechnung erstellt');
  806.         return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
  807.     }
  808.     /**
  809.      * @Route("/{id}", name="order_delete", methods="DELETE")
  810.      */
  811.     public function delete(Request $requestOrder $order): Response
  812.     {
  813.         if ($this->isCsrfTokenValid('delete' $order->getId(), $request->request->get('_token'))) {
  814.             $em $this->getDoctrine()->getManager();
  815.             $em->remove($order);
  816.             $em->flush();
  817.         }
  818.         return $this->redirectToRoute('order_index');
  819.     }
  820.     protected function updateParticipantsOfOrder(Order $order)
  821.     {
  822.         if (count($order->getOrderItems()) > 0) {
  823.             foreach ($order->getOrderItems() as $orderItem) {
  824.                 if (count($orderItem->getParticipants()) > 0) {
  825.                     foreach ($orderItem->getParticipants() as $participant) {
  826.                         $participant->updateFieldsFromPerson();
  827.                     }
  828.                 }
  829.             }
  830.         }
  831.     }
  832.     private function createInvoiceRecipientValues($persons$customer)
  833.     {
  834.         $res[] = $customer;
  835.         foreach ($persons as $person) {
  836.             $res[] = $person;
  837.         }
  838.         return $res;
  839.     }
  840.     /**
  841.      * isInvoiceWithCancillation
  842.      *
  843.      * Checks whether one of the invoices is a cancellation invoice
  844.      *
  845.      * @param  Collection $invoices
  846.      * @return boolean
  847.      */
  848.     private function isInvoiceWithCancillation(Collection $invoices)
  849.     {
  850.         $cancelation false;
  851.         if (empty($invoices)) return $cancelation;
  852.         $counter count($invoices);
  853.         if ($counter || !($invoices[$counter 1]->isCancellation())) return $cancelation;
  854.         foreach ($invoices as $invoice) {
  855.             if ($invoice->isCancellation()) {
  856.                 $cancelation true;
  857.                 break;
  858.             }
  859.         }
  860.         return $cancelation;
  861.     }
  862.     /**
  863.      * @Route("/changestatus/{id}/{status}", name="change_status")
  864.      */
  865.     public function changeStatus(Order $order$status): Response
  866.     {
  867.         $em $this->getDoctrine()->getManager();
  868.         $newstatus $order->setStatus($status);
  869.         $em->persist($newstatus);
  870.         $em->flush();
  871.         return $this->json([
  872.             'success' => 'Der Status wurde geändert.'
  873.         ]);
  874.     }
  875.     /**
  876.      * @Route("/sendordermail/{id}", name="send_order_mail")
  877.      */
  878.     public function sendordermail(Order $orderPersonRepository $personRepoEmailHistoryService $emailHistoryServiceMailerService $mailerServiceConnection $connection): Response
  879.     {
  880.         foreach ($order->getOrderItems() as $item) {
  881.             /////////////////////////////////// FIELDS Start //////////////////////////////////////
  882.             // Fetch course fields
  883.             $sql 'SELECT
  884.             f.*,
  885.             d.value_text,
  886.             d.value_integer
  887.         FROM
  888.             course_field f
  889.         LEFT JOIN
  890.             course_data d
  891.             ON 
  892.             d.field_id = f.id AND
  893.             d.course_id = :courseId
  894.         WHERE f.certificate = 0';
  895.             $stmt $connection->prepare($sql);
  896.             $stmt->bindValue(
  897.                 'courseId',
  898.                 $item->getCourseOccurrence()->getCourse()->getId()
  899.             );
  900.             $stmt->executeQuery();
  901.             $result $stmt->fetchAll();
  902.             $fields = [];
  903.             foreach ($result as $index => $field) {
  904.                 if (!empty($field['category'])) {
  905.                     if (!$item->getCourseOccurrence()->getCourse()->getCategory()) {
  906.                         continue;
  907.                     }
  908.                     if (!in_array($item->getCourseOccurrence()->getCourse()->getCategory()->getId(), json_decode($field['category'], true))) {
  909.                         continue;
  910.                     }
  911.                 }
  912.                 if (!empty($field['course_type'])) {
  913.                     if (!$item->getCourseOccurrence()->getCourse()->getType()) {
  914.                         continue;
  915.                     }
  916.                     if (!in_array($item->getCourseOccurrence()->getCourse()->getType()->getId(), json_decode($field['course_type'], true))) {
  917.                         continue;
  918.                     }
  919.                 }
  920.                 $fields[] = [
  921.                     'id' => $field['id'],
  922.                     'name' => $field['name'],
  923.                     'value' => !empty($field['value_integer']) ? $field['value_integer'] : $field['value_text'],
  924.                 ];
  925.             }
  926.             $order->setFields($fields);
  927.         $sentMessage $mailerService->sendCheckoutConfirmMessage($order);
  928.         $customer $order->getCustomer();
  929.         $emailHistoryService->saveProtocolEntryFromOrder(
  930.             $order,
  931.             $this->getCurrentClient(),
  932.             $customer,
  933.             'versandt',
  934.             $sentMessage['subject'],
  935.             $sentMessage['message'],
  936.             'Bestellbestätigung gesendet',
  937.             $sentMessage['email']
  938.         );
  939.         $message "Bestellbestätigung ist versendet" ;
  940.         $this->addFlash('notice'$message);
  941.         return $this->redirectToRoute('order_index');
  942.     }
  943. }
  944. }