src/Controller/OrderController.php line 556

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