<?php
 
 
namespace App\Controller;
 
 
use App\Entity\Order;
 
use App\Entity\Invoice;
 
use App\Form\OrderType;
 
use App\Entity\WaitItem;
 
use App\Entity\OrderItem;
 
use App\Service\UiService;
 
use App\Form\OrderStatusType;
 
use App\Service\OrderService;
 
use Doctrine\DBAL\Connection;
 
use App\Entity\OrderItemPerson;
 
use App\Service\InvoiceService;
 
use App\Form\OrderItemPersonCopy;
 
use App\Repository\OrderRepository;
 
use App\Repository\PersonRepository;
 
use App\Repository\InvoiceRepository;
 
use App\Service\ConfigurationService;
 
use App\Form\OrderItemPersonCancelDate;
 
use App\Entity\CourseSubscriptionBooking;
 
use Doctrine\Persistence\ManagerRegistry;
 
use Doctrine\Common\Collections\Collection;
 
use Psr\Log\LoggerInterface;
 
use Symfony\Component\HttpFoundation\Request;
 
use App\Repository\CourseOccurrenceRepository;
 
use Symfony\Component\HttpFoundation\Response;
 
use Symfony\Component\Routing\Annotation\Route;
 
use App\Repository\CourseOccurrenceTimeRepository;
 
use Symfony\Component\HttpFoundation\RequestStack;
 
use Menke\UserBundle\Controller\AbstractClientableController;
 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
 
 
/**
 
 * @Route("/order")
 
 * @IsGranted("ROLE_MANAGER")
 
 * @IsGranted("ROLE_ADMIN")
 
 */
 
class OrderController extends AbstractClientableController
 
{
 
    const LISTING_LIMIT = 25;
 
 
    /**
 
     * @Route("/", name="order_index", methods="GET")
 
     */
 
    public function index(
 
        UiService $uiService,
 
        OrderRepository $orderRepo,
 
        Request $request,
 
        RequestStack $requestStack
 
    ): Response {
 
        $order = $uiService->getSortOrder('order-index-listing');
 
 
        $filterOrders = $request->get('orderAction');
 
        if ($filterOrders) {
 
            $requestStack->getSession()->set('orderFilter', $filterOrders);
 
        } else {
 
            $requestStack->getSession()->set('orderFilter', null);
 
        }
 
 
        $orders = $orderRepo->getByClientPaged(
 
            $this->getCurrentClient(),
 
            self::LISTING_LIMIT,
 
            $order['orderDirection'] ?? 'desc',
 
            $order['orderBy'] ?? 'date',
 
            1,
 
            ($filterOrders) ? $filterOrders : null
 
        );
 
 
        return $this->render('order/index.html.twig', [
 
            'uiService' => $uiService,
 
            'orders' => $orders->getIterator(),
 
            'total' => $orders->count(),
 
            'pages' => ceil($orders->count() / self::LISTING_LIMIT),
 
            'page' => 1,
 
        ]);
 
    }
 
 
 
 
 
    /**
 
     * @Route("/{page}/{orderby}/{order}", name="order_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
 
     */
 
    public function indexListing(
 
        OrderRepository $orderRepo,
 
        UiService $uiService,
 
        $page,
 
        $orderby,
 
        $order,
 
        RequestStack $requestStack
 
    ): Response {
 
        $uiService->storeSortOrder('order-index-listing', $orderby, $order);
 
 
        $orders = $orderRepo->getByClientPaged(
 
            $this->getCurrentClient(),
 
            self::LISTING_LIMIT,
 
            $order,
 
            $orderby,
 
            $page,
 
            $requestStack->getSession()->get('orderFilter')
 
        );
 
 
        return $this->render('order/_index_listing.html.twig', [
 
            'orders' => $orders->getIterator(),
 
            'total' => $orders->count(),
 
            'pages' => ceil($orders->count() / self::LISTING_LIMIT),
 
            'page' => $page,
 
        ]);
 
    }
 
 
    /**
 
     * @Route("/new/{return}", name="order_new", methods="GET|POST")
 
     */
 
    public function new(
 
        Request $request,
 
        $return = '',
 
        PersonRepository $personRepo,
 
        ConfigurationService $configService,
 
        OrderService $orderService,
 
        CourseOccurrenceRepository $courseOccurrenceRepository
 
    ): Response {
 
        $customer = null;
 
        $invoiceRecipient = null;
 
        $isEmptyParticipants = false;
 
 
        if ($return) {
 
            $customer = $personRepo->find($return);
 
            $invoiceRecipient = $personRepo->getInvoiceReciepientMembers($return);
 
 
            $invoiceRecipient = $this->createInvoiceRecipientValues($invoiceRecipient, $customer);
 
            $customerChildrens = $personRepo->getMembersByClient($customer);
 
 
            $isEmptyParticipants = (empty($customerChildrens)) ? true : false;
 
        }
 
 
        $order = new Order();
 
        $form = $this->createForm(OrderType::class, $order, [
 
            'client' => $this->getCurrentClient(),
 
            'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
 
            'customer' => $customer,
 
            'invoiceRecipient' => $invoiceRecipient,
 
            'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
 
        ]);
 
 
        $form->handleRequest($request);
 
 
        // Check if creation is possible
 
        if ($form->isSubmitted() && $form->isValid()) {
 
            foreach ($order->getOrderItems() as $orderItem) {
 
 
                // Skip participants check for free items
 
                if ($orderItem->getCourseOccurrence() === null) {
 
                    continue;
 
                }
 
 
                // Check if order item has at least one participant
 
                if (count($orderItem->getParticipants()) == 0) {
 
                    $this->addFlash('error', 'Der Kurs enthält keine Teilnehmer.');
 
                    return $this->redirectToRoute('order_new', ['return' => $return]);
 
                }
 
            }
 
 
            if (!$order->checkCustomerData($customer)) {
 
                $this->addFlash('error', 'Die Kundendaten sind unvollständig. Es kann keine neue Bestellung angelegt werden.');
 
                if ($return) {
 
                    return $this->redirectToRoute('customer_orders', ['id' => $return]);
 
                } else {
 
                    return $this->redirectToRoute('order_index');
 
                }
 
            }
 
 
            $em = $this->getDoctrine()->getManager();
 
            $allItemsBookable = true;
 
            $occurrences = [];
 
            foreach ($order->getOrderItems() as $orderItem) {
 
                if ($orderItem->getCourseOccurrence()) {
 
 
                    $occurrence = $orderItem->getCourseOccurrence();
 
                    if (!$occurrence->isBookable($orderItem->getQuantity()) && $occurrence->getReservationAllowed()) {
 
                        $waitItem = WaitItem::fromOrderItem($orderItem);
 
                        $em->persist($waitItem);
 
                        foreach ($orderItem->getParticipants() as $participant) {
 
                            $orderItem->removeParticipant($participant);
 
                        }
 
                        $order->addWaitItem($waitItem);
 
                        $order->removeOrderItem($orderItem);
 
                        $this->addFlash('error', 'Im Kurs "' . $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar. Die Buchung wurde stattdessen zur Warteliste hinzugefügt.');
 
                    } elseif (!$occurrence->isBookable($orderItem->getQuantity()) && !$occurrence->getReservationAllowed()) {
 
                        $allItemsBookable = false;
 
                        $this->addFlash('error', 'Im Kurs "' . $occurrence->getTitle() . '" sind nicht mehr genug Plätze verfügbar.');
 
                    } else {
 
                        if ($orderItem->getCourseOccurrence()->getCourse()->getCourseNature() == 'CourseSubscription') {
 
                            $courseSubscriptionBooking = new CourseSubscriptionBooking($orderItem, $orderItem->getCourse());
 
                            $courseSubscriptionBooking->setOrderItem($orderItem);
 
                            $courseSubscriptionBooking->setCourse($orderItem->getCourseOccurrence()->getCourse());
 
                            $courseSubscriptionBooking->setCourseSubscription($orderItem->getCourseOccurrence()->getCourse()->getSubscription());
 
                            $orderItem->setCourseSubscriptionBooking($courseSubscriptionBooking);
 
                            $em->persist($courseSubscriptionBooking);
 
                        }
 
                        $occurrence->bookSlots($orderItem->getQuantity());
 
                        $occurrences[] = $occurrence;
 
                    }
 
                }
 
            }
 
            $this->updateParticipantsOfOrder($order);
 
            $em->flush();
 
 
            if ($allItemsBookable) {
 
                if (count($order->getOrderItems()) > 0 ||  count($order->getWaitItems()) > 0) {
 
                    $order->setClient($this->getCurrentClient());
 
                    $order->setCustomer($customer);
 
                    $order->setCustomerData($customer);
 
                    $order->setNumber($configService->getNewOrderNumberByClient($this->getCurrentClient()));
 
                    $em->persist($order);
 
                    $em->flush();
 
 
                    foreach ($occurrences as $occurrence) {
 
                        $occurrence->flushBooking();
 
                    }
 
 
                    // Ggf. nachfolgende Bestellungen fuer Abokurse generieren und speichern
 
                    $flashs = [];
 
                    $followingOrders = $orderService->generateOrdersForSubscriptionCoursesAllFollowingOccurrences($this->getCurrentClient(), $order, $flashs);
 
                    foreach ($followingOrders as $orderToSave) {
 
                        $em->persist($orderToSave);
 
                    }
 
                    foreach ($flashs as $flashToShow) {
 
                        foreach ($flashToShow as $key => $value) {
 
                            $this->addFlash($key, $value);
 
                        }
 
                    }
 
                    $em->flush();
 
                }
 
 
                if ($return) {
 
                    return $this->redirectToRoute('customer_orders', ['id' => $return]);
 
                } else {
 
                    return $this->redirectToRoute('order_index');
 
                }
 
            }
 
        }
 
 
        return $this->render('order/new.html.twig', [
 
            'order' => $order,
 
            'form' => $form->createView(),
 
            'customer' => $customer,
 
            'invoiceRecipient' => $invoiceRecipient,
 
            'invalidCustomerData' => !$order->checkCustomerData($customer),
 
            'isEmptyParticipants' => $isEmptyParticipants,
 
            'isInvoiceClosed' => false
 
        ]);
 
    }
 
 
 
 
    /**
 
     * @Route("/{id}", name="order_show", methods="GET|POST", requirements={"id"="\d+"})
 
     */
 
    public function show(
 
        Request $request,
 
        Order $order,
 
        InvoiceRepository $invoiceRepo
 
    ): Response {
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $order);
 
 
        $form = $this->createForm(OrderStatusType::class, $order);
 
        $form->handleRequest($request);
 
 
        if ($form->isSubmitted() && $form->isValid()) {
 
            $this->getDoctrine()->getManager()->flush();
 
 
            return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
 
        }
 
 
        $orderedInvoices = $invoiceRepo->getOrderedInvoices($order->getId());
 
        $isInvoiceWithCancillation = $this->isInvoiceWithCancillation($order->getInvoices());
 
 
        return $this->render('order/show.html.twig', [
 
            'order' => $order,
 
            'form' => $form->createView(),
 
            'isInvoiceWithCancillation' => $isInvoiceWithCancillation,
 
            'orderedInvoices' => $orderedInvoices
 
        ]);
 
    }
 
 
    /**
 
     * @Route("/search/{occurrenceId}/{timeId}", name="order_search", methods="GET|POST", requirements={"id"="\d+"})
 
     */
 
    public function search(
 
        Request $request,
 
        Connection $connection,
 
        CourseOccurrenceTimeRepository $timeRepository
 
    ): Response {
 
        $time = $timeRepository->find($request->get('timeId'));
 
 
        $sql = 'SELECT
 
            oi.*
 
        FROM
 
            customer_order_item oi,
 
            course_occurrence o
 
        WHERE
 
            o.id = oi.course_occurrence_id AND
 
            o.start = "' . $time->getStart()->format('Y-m-d H:i:s') . '"
 
        GROUP BY
 
            oi._order_id';
 
 
        $result = $connection->fetchAssoc($sql);
 
 
        if (empty($result)) {
 
 
            $sql = 'SELECT
 
                oi.*
 
            FROM
 
                wait_item oi,
 
                course_occurrence o
 
            WHERE
 
                o.id = oi.course_occurrence_id AND
 
                o.start = "' . $time->getStart()->format('Y-m-d H:i:s') . '"
 
            GROUP BY
 
                oi._order_id';
 
 
            $result = $connection->fetchAssoc($sql);
 
        }
 
 
        return $this->redirectToRoute('order_show', ['id' => $result['_order_id']]);
 
    }
 
 
    /**
 
     * @Route("/{id}/edit/{return}", name="order_edit", methods="GET|POST", requirements={"id"="\d+","return"="\d+"})
 
     */
 
    public function edit(
 
        Request $request,
 
        Order $order,
 
        $return = '',
 
        ConfigurationService $configService,
 
        PersonRepository $personRepo
 
    ): Response {
 
        $isEmptyParticipants = false;
 
        $invoiceRecipient = null;
 
        $isInvoiceClosed = false;
 
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $order);
 
 
        $customer = null;
 
        if ($order->getCustomer()) {
 
            $customer = $order->getCustomer();
 
        }
 
 
        if (
 
            $order->getInvoices()->first() &&
 
            $order->getInvoices()->first()->getStatus() == Invoice::STATUS_CLOSED
 
        ) {
 
            $isInvoiceClosed = true;
 
        }
 
 
 
        if ($return) {
 
            $customer = $personRepo->find($return);
 
            $invoiceRecipient = $personRepo->getInvoiceReciepientMembers($return);
 
 
            $invoiceRecipient = $this->createInvoiceRecipientValues($invoiceRecipient, $customer);
 
            $customerChildrens = $personRepo->getMembersByClient($customer);
 
 
            $isEmptyParticipants = (empty($customerChildrens)) ? true : false;
 
        }
 
 
        if ($order->getStatus() != Order::STATUS_PENDING) {
 
            $this->addFlash('notice', 'Die Bestellung kann nur bearbeitet werden wenn Sie in Wartestellung ist.');
 
            if ($return) {
 
                return $this->redirectToRoute('customer_orders', ['id' => $return]);
 
            } else {
 
                return $this->redirectToRoute('order_index');
 
            }
 
        }
 
 
        $form = $this->createForm(OrderType::class, $order, [
 
            'client' => $this->getCurrentClient(),
 
            'taxes' => $configService->getTaxConfigbyClient($this->getCurrentClient()),
 
            'invoiceRecipient' => $invoiceRecipient,
 
            'customer' => $customer,
 
            'form_type' => OrderType::TYPE_CREATE_FOR_CUSTOMER
 
        ]);
 
        $form->handleRequest($request);
 
 
        if ($form->isSubmitted() && $form->isValid()) {
 
 
            $this->updateParticipantsOfOrder($order);
 
            $em = $this->getDoctrine()->getManager();
 
 
            foreach ($order->getOrderItems() as $item) {
 
                if (!$item->isFree() && $item->getCourseOccurrence()) {
 
                    $item->setName($item->getCourseOccurrence()->getTitle());
 
                    $em->persist($item);
 
                } else {
 
                    $item->setCourseOccurrence(null);
 
                    $em->persist($item);
 
                }
 
            }
 
 
            $em->flush();
 
            $this->addFlash('notice', 'Die Bestellung wurde bearbeitet.');
 
 
            return $this->redirectToRoute('order_index');
 
            // }
 
        }
 
 
        return $this->render('order/edit.html.twig', [
 
            'order' => $order,
 
            'form' => $form->createView(),
 
            'customer' => $customer,
 
            'isEmptyParticipants' => $isEmptyParticipants,
 
            'invoiceRecipient' => $invoiceRecipient,
 
            'isInvoiceClosed' => $isInvoiceClosed
 
        ]);
 
    }
 
 
    /**
 
     * @Route("/{id}/cancel", name="order_cancel", methods="POST")
 
     */
 
    public function cancel(
 
        Request $request,
 
        Order $order,
 
        ConfigurationService $configService,
 
        OrderService $orderService
 
    ): Response {
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $order);
 
 
        if ($this->isCsrfTokenValid('cancel' . $order->getId(), $request->request->get('_token'))) {
 
            $em = $this->getDoctrine()->getManager();
 
 
            // If order item is connected to time slot mark it bookable again
 
            foreach ($order->getOrderItems() as $orderItem) {
 
                if ($time = $orderItem->getCourseOccurrenceTime()) {
 
                    $time->setAvailability('Bookable');
 
                    $time->setOrderItem(null);
 
                }
 
            }
 
 
            foreach ($order->getWaitItems() as $waitItem) {
 
 
                if ($time = $waitItem->getCourseOccurrenceTime()) {
 
                    $time->setAvailability('Requestable');
 
                    $time->setWaitItem(null);
 
                }
 
            }
 
 
            foreach ($order->getInvoices() as $invoice) {
 
                if (!$invoice->isCancelled() && !$invoice->isCancellation()) {
 
                    $cancellation = $orderService->createCancellation($invoice);
 
                    $cancellation->setSignedBy($this->getCurrentUser());
 
                    $invoice->setCancelled(true);
 
                    $em->persist($cancellation);
 
                }
 
            }
 
 
            $order->setStatus(Order::STATUS_CANCELLED);
 
            $orderService->calculateCancelOrderItems($order);
 
 
            $em->flush();
 
            $this->addFlash('notice', 'Bestellung storniert');
 
        }
 
 
        return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
 
    }
 
 
    /**
 
     * @Route("/set-cancel-date/{id}", name="participant_set-cancel-date")
 
     */
 
    public function setCancelDateForParticicpant(
 
        Request $request,
 
        OrderItemPerson $participant,
 
        OrderService $orderService,
 
        RequestStack $requestStack,
 
        ManagerRegistry $managerRegistry,
 
        LoggerInterface $logger
 
    ): Response {
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $participant->getOrderItem()->getOrder());
 
 
        $form = $this->createForm(OrderItemPersonCancelDate::class, null, [
 
            'action' => $this->generateUrl('participant_set-cancel-date', ['id' => $participant->getId()])
 
        ]);
 
        $form->handleRequest($request);
 
 
        $participant->setCancelled($orderService->getCancelDateForParticipantInCourse($this->getCurrentClient(), $participant));
 
        
 
        if ($form->isSubmitted() && $form->isValid()) {
 
 
            /**
 
             * @var \DateTimeInterface $cancelDate
 
             */
 
            $cancelDate = $form->getData()['cancelDate'];
 
 
            // Kuendigungsdatum in entsprechenden Teilnehmereintrag im Kurs schreiben
 
            $participant->setCancelled($cancelDate);
 
 
            $em = $managerRegistry->getManager();
 
 
            $logger->debug("cancel date:" . $cancelDate->format("d-m-Y H:i:s"));
 
 
            $booking = $participant->getOrderItem()->getCourseSubscriptionBooking();
 
            if (!empty($booking)) {
 
                $terminationPeriod = $booking->getCourseSubscription()->getTerminationPeriodMonths();
 
                $logger->debug($terminationPeriod);
 
 
                $diff = $cancelDate->diff(new \DateTime());
 
 
                // if($diff->m < $terminationPeriod) {
 
                    $cancellationTimestamp = strtotime('+' . $terminationPeriod . ' months', $cancelDate->getTimeStamp());
 
                // } else {
 
                //    $cancellationTimestamp = $cancelDate->getTimestamp();
 
                //}
 
 
                $cancelDate->setTimestamp($cancellationTimestamp);
 
 
                $logger->debug($cancellationTimestamp);
 
                //dd($terminationPeriod, $cancellationTimestamp, $cancelDate);
 
            }
 
 
            $result = $orderService->setCancelDateForParticipantInCourse(
 
                $this->getCurrentClient(),
 
                $participant,
 
                $cancelDate
 
            );
 
 
            //$logger->debug("TEST UND SO " . $oipWithCancelDate->getCancelled()->format("d-m-Y H:i:s"));
 
 
            $em->flush();
 
 
            // Aktive Eintraege/Bestellpositionen/Bestellungen fuer Kurstermine nach dem Kuendigungsdatum erhalten
 
            $oipsToCancel = $orderService->getAllActiveParticipationsAfterCancelDateByParticipant(
 
                $this->getCurrentClient(),
 
                $participant
 
            );
 
 
            $logger->debug("oipsToCancel: " . json_encode($oipsToCancel));
 
 
            // Diese Eintraege einzeln durchlaufen und stornieren
 
            foreach ($oipsToCancel as $oipToCancel) {
 
 
                // Bei schon vorhandenen Rechnungen ggf. Storno-Rechnungen erstellen
 
                foreach ($oipToCancel->getOrderItem()->getOrder()->getInvoices() as $invoice) {
 
                    if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($oipToCancel->getOrderItem())) {
 
                        $cancellation = $orderService->createCancellation($invoice, $oipToCancel->getOrderItem(), $oipToCancel->getId());
 
                        $cancellation->setSignedBy($this->getCurrentUser());
 
                        $em->persist($cancellation);
 
                    }
 
                }
 
 
                // Eintrag stornieren
 
                $orderService->cancelOrderItemParticipant($oipToCancel->getOrderItem(), $oipToCancel->getId());
 
 
                // Ggf. Bestellposition stornieren
 
                if (!$oipToCancel->getOrderItem()->hasUncancelledParticipants()) {
 
                    $oipToCancel->getOrderItem()->setStatus(OrderItem::STATUS_CANCELLED);
 
                    foreach ($oipToCancel->getOrderItem()->getMaterialCosts() as $materialCost) {
 
                        $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
 
                    }
 
                }
 
 
                // Ggf. Bestellung stornieren
 
                if (!$oipToCancel->getOrderItem()->getOrder()->hasUncancelledItems()) {
 
                    $oipToCancel->getOrderItem()->getOrder()->setStatus(Order::STATUS_CANCELLED);
 
                }
 
                $orderService->calculateCancelOrderItem($oipToCancel->getOrderItem());
 
            }
 
 
            // Aenderungen in Datenbank speichern
 
            $em->flush();
 
 
            $flashExists = false;
 
            foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
 
                if ($flashType == 'notice' && $flashTitle == 'Kündigungsdatum eingetragen') $flashExists = true;
 
            }
 
            if (!$flashExists) $this->addFlash('notice', 'Kündigungsdatum eingetragen');
 
 
            $route = $request->headers->get('referer');
 
 
            return $this->redirect($route);
 
        }
 
 
        return $this->render('course/_set-cancel-date.html.twig', [
 
            'person' => $participant->getPerson(),
 
            'form' => $form->createView(),
 
            'cancelDate' => $participant->getCancelled(),
 
            'today' => new \DateTime()
 
        ]);
 
    }
 
 
    /**
 
     * @Route("/{id}/cancel-item/{participantId}/{return}", name="order-item_cancel", methods="GET")
 
     */
 
    public function cancelItem(
 
        Request $request,
 
        OrderItem $orderItem,
 
        int $participantId = 0,
 
        string $return = '',
 
        ConfigurationService $configService,
 
        OrderService $orderService
 
    ): Response {
 
        $order = $orderItem->getOrder();
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $order);
 
        $em = $this->getDoctrine()->getManager();
 
 
        foreach ($order->getInvoices() as $invoice) {
 
            if (!$invoice->isCancelled() && !$invoice->isCancellation() && $invoice->containsOrderItem($orderItem)) {
 
                $cancellation = $orderService->createCancellation($invoice, $orderItem, $participantId);
 
                $cancellation->setSignedBy($this->getCurrentUser());
 
                $em->persist($cancellation);
 
            }
 
        }
 
 
        if ($participantId > 0) {
 
            $orderService->cancelOrderItemParticipant($orderItem, $participantId);
 
        } else {
 
            $orderItem->cancelAllParticipants();
 
        }
 
 
        if (!$orderItem->hasUncancelledParticipants()) {
 
            $orderItem->setStatus(OrderItem::STATUS_CANCELLED);
 
            foreach ($orderItem->getMaterialCosts() as $materialCost) {
 
                $materialCost->setStatus(OrderItem::STATUS_CANCELLED);
 
            }
 
        }
 
        if (!$order->hasUncancelledItems()) {
 
            $order->setStatus(Order::STATUS_CANCELLED);
 
        }
 
        $orderService->calculateCancelOrderItem($orderItem);
 
 
        $em->flush();
 
        $this->addFlash('notice', 'Kurs storniert');
 
 
        // return $this->redirect(urldecode($return));
 
        return $this->redirectToRoute('course_invoices', ['id' => $request->get('course_id')]);
 
    }
 
 
    /**
 
     * @Route("/copy-participant/{id}", name="participant_copy-to-other-occurrence")
 
     */
 
    public function copyParticipantToOtherOccurrence(
 
        Request $request,
 
        OrderItemPerson $participant,
 
        OrderService $orderService,
 
        CourseOccurrenceRepository $coRepo,
 
        RequestStack $requestStack
 
    ): Response {
 
        $this->denyAccessUnlessGranted('ROLE_MANAGER', $participant->getOrderItem()->getOrder());
 
 
        $selectableOccurrences = $orderService->getAllOccurrencesOfCourseAParticipantIsNotInBeforeCancelDate($this->getCurrentClient(), $participant);
 
 
        $selectableOccurrencesArray = [];
 
        foreach ($selectableOccurrences as $selectableOccurrence) {
 
            $selectableOccurrencesArray[$selectableOccurrence->getStart()->format('d.m.Y') . ' - ' . $selectableOccurrence->getEnd()->format('d.m.Y')] = $selectableOccurrence->getId();
 
        }
 
 
        $form = $this->createForm(OrderItemPersonCopy::class, null, [
 
            'occurrences' => $selectableOccurrencesArray,
 
            'action' => $this->generateUrl('participant_copy-to-other-occurrence', ['id' => $participant->getId()])
 
        ]);
 
        $form->handleRequest($request);
 
 
        if ($form->isSubmitted() && $form->isValid()) {
 
            $em = $this->getDoctrine()->getManager();
 
            $flashs = [];
 
            $orders = [];
 
 
            foreach ($form->getData()['occurrences'] as $occurrenceId) {
 
 
                $flash = [];
 
                $occurrence = $coRepo->find($occurrenceId);
 
                $newOrder = $orderService->generateOrderForCourseOccurrenceFromOrderItemPerson(
 
                    $this->getCurrentClient(),
 
                    $participant,
 
                    $occurrence,
 
                    $flash,
 
                    false
 
                );
 
                if ($newOrder !== null) {
 
                    $orders[] = $newOrder;
 
                }
 
                if (count($flash) > 0) {
 
                    $flashs[] = $flash;
 
                }
 
            }
 
 
            foreach ($orders as $orderToSave) {
 
                $em->persist($orderToSave);
 
            }
 
            foreach ($flashs as $flashToShow) {
 
                foreach ($flashToShow as $key => $value) {
 
                    $this->addFlash($key, $value);
 
                }
 
            }
 
 
            // Aenderungen in Datenbank speichern
 
            $em->flush();
 
 
            $flashExists = false;
 
            foreach ($requestStack->getSession()->all() as $flashType => $flashTitle) {
 
                if ($flashType == 'notice' && $flashTitle == 'Teilnehmer in ' . count($orders) . ' weitere Termine übernommen') $flashExists = true;
 
            }
 
            if (!$flashExists) $this->addFlash('notice', 'Teilnehmer in ' . count($orders) . ' weitere Termine übernommen');
 
 
            return $this->redirectToRoute('course_participants', ['id' => $participant->getOrderItem()->getCourseOccurrence()->getCourse()->getId()]);
 
        }
 
 
        return $this->render('course/_copy-to-occurrence.html.twig', [
 
            'person' => $participant->getPerson(),
 
            'form' => $form->createView(),
 
        ]);
 
    }
 
 
    /**
 
     * @Route("/{id}/create-invoice", name="order_invoice_create", methods="GET")
 
     */
 
    public function createInvoice(
 
        Request $request,
 
        Order $order,
 
        InvoiceService $invoiceService
 
    ): Response {
 
        $results = $invoiceService->createInvoiceFromOrder($order);
 
 
        $em = $this->getDoctrine()->getManager();
 
 
        //Update the order status
 
        $newOrderState = $order->setStatus(Order::STATUS_PROCESSING);
 
        $em->persist($newOrderState);
 
 
        foreach ($results['attendees'] as $attendee) {
 
            $em->persist($attendee);
 
        }
 
 
        $em->persist($results['invoice']);
 
        $em->flush();
 
 
        $this->addFlash('notice', ' Rechnung erstellt');
 
 
        return $this->redirectToRoute('order_show', ['id' => $order->getId()]);
 
    }
 
 
    /**
 
     * @Route("/{id}", name="order_delete", methods="DELETE")
 
     */
 
    public function delete(Request $request, Order $order): Response
 
    {
 
        if ($this->isCsrfTokenValid('delete' . $order->getId(), $request->request->get('_token'))) {
 
            $em = $this->getDoctrine()->getManager();
 
            $em->remove($order);
 
            $em->flush();
 
        }
 
 
        return $this->redirectToRoute('order_index');
 
    }
 
 
    protected function updateParticipantsOfOrder(Order $order)
 
    {
 
        if (count($order->getOrderItems()) > 0) {
 
            foreach ($order->getOrderItems() as $orderItem) {
 
                if (count($orderItem->getParticipants()) > 0) {
 
                    foreach ($orderItem->getParticipants() as $participant) {
 
                        $participant->updateFieldsFromPerson();
 
                    }
 
                }
 
            }
 
        }
 
    }
 
 
    private function createInvoiceRecipientValues($persons, $customer)
 
    {
 
        $res[] = $customer;
 
 
        foreach ($persons as $person) {
 
            $res[] = $person;
 
        }
 
 
        return $res;
 
    }
 
 
    /**
 
     * isInvoiceWithCancillation
 
     *
 
     * Checks whether one of the invoices is a cancellation invoice
 
     *
 
     * @param  Collection $invoices
 
     * @return boolean
 
     */
 
    private function isInvoiceWithCancillation(Collection $invoices)
 
    {
 
        $cancelation = false;
 
 
        if (empty($invoices)) return $cancelation;
 
 
        $counter = count($invoices);
 
        if ($counter < 2 || !($invoices[$counter - 1]->isCancellation())) return $cancelation;
 
 
        foreach ($invoices as $invoice) {
 
            if ($invoice->isCancellation()) {
 
                $cancelation = true;
 
 
                break;
 
            }
 
        }
 
 
        return $cancelation;
 
    }
 
 
   /**
 
     * @Route("/changestatus/{id}/{status}", name="change_status")
 
     */
 
 
    public function changeStatus(Order $order, $status): Response { 
 
        $em = $this->getDoctrine()->getManager();
 
        $newstatus = $order->setStatus($status);
 
        $em->persist($newstatus);
 
        $em->flush();
 
        return $this->json([
 
            'success' => 'Der Status wurde geändert.'
 
        ]);
 
    }
 
 
}