src/Controller/InvoiceController.php line 270

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\Entity\WaitItem;
  7. use App\Form\InvoiceType;
  8. use App\Service\UiService;
  9. use App\Form\CsvImportType;
  10. use App\Service\PdfService;
  11. use App\Form\InvoiceOnlyType;
  12. use App\Entity\InvoicePayment;
  13. use App\Service\MailerService;
  14. use App\Service\InvoiceService;
  15. use App\Service\PaymentService;
  16. use App\Service\SepaXmlService;
  17. use App\Entity\Dto\CsvImportDto;
  18. use App\Service\CsvImportService;
  19. use App\Repository\PersonRepository;
  20. use App\Service\EmailHistoryService;
  21. use App\Repository\InvoiceRepository;
  22. use App\Service\ConfigurationService;
  23. use App\Service\Exception\ServiceException;
  24. use App\Repository\InvoicePaymentRepository;
  25. use App\Repository\InvoiceReminderRepository;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\Routing\Annotation\Route;
  29. use Doctrine\Common\Collections\ArrayCollection;
  30. use App\Repository\InvoiceItemAttendeesRepository;
  31. use Symfony\Component\HttpFoundation\RequestStack;
  32. use Symfony\Component\HttpFoundation\RedirectResponse;
  33. use Menke\UserBundle\Controller\AbstractClientableController;
  34. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  35. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  36. /**
  37.  * @Route("/invoice")
  38.  * @IsGranted("ROLE_MANAGER")
  39.  */
  40. class InvoiceController extends AbstractClientableController
  41. {
  42.     const LISTING_LIMIT 20;
  43.     private function generateUniqueFileName()
  44.     {
  45.         return md5(uniqid());
  46.     }
  47.     /**
  48.      * @Route("/", name="invoice_index", methods="GET|POST")
  49.      */
  50.     public function index(
  51.         Request $request,
  52.         InvoiceRepository $invoiceRepo,
  53.         CsvImportService $importService,
  54.         UiService $uiService,
  55.         RequestStack $requestStack,
  56.         PaymentService $paymentService
  57.     ): Response {
  58.         $order $uiService->getSortOrder('invoice-index-listing');
  59.         //Check for unset invoice status
  60.         $this->checkForUnsetInvoiceStatus($invoiceRepo$paymentService);
  61.         $filterInvoices $request->get('action');
  62.         if ($filterInvoices) {
  63.             $requestStack->getSession()->set('filter'$filterInvoices);
  64.         } else {
  65.             $requestStack->getSession()->set('filter'null);
  66.         }
  67.         $invoice $invoiceRepo->getByClientPaged(
  68.             $this->getCurrentClient(),
  69.             self::LISTING_LIMIT,
  70.             $order['orderDirection'] ?? 'desc',
  71.             $order['orderBy'] ?? 'id',
  72.             1,
  73.             ($filterInvoices) ? $filterInvoices null
  74.         );
  75.         $csvImportDto = new CsvImportDto();
  76.         $form $this->createForm(CsvImportType::class, $csvImportDto);
  77.         $form->handleRequest($request);
  78.         if ($form->isSubmitted() && $form->isValid()) {
  79.             $fileName =
  80.                 md5(uniqid()) . '.' $csvImportDto->file->guessExtension();
  81.             try {
  82.                 $csvImportDto->file->move(
  83.                     $this->getParameter('import_directory'),
  84.                     $fileName
  85.                 );
  86.                 $fullFileName $this->getParameter('import_directory') . '/' $fileName;
  87.             } catch (FileException $e) {
  88.                 $this->addFlash(
  89.                     'error',
  90.                     'Beim Datei-Upload ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal.'
  91.                 );
  92.                 return $this->redirectToRoute('invoice_index');
  93.             }
  94.             $result $importService->updateInvoiceStatus(
  95.                 $fullFileName,
  96.                 $this->getCurrentClient()
  97.             );
  98.             if (is_array($result)) {
  99.                 $message 'Beim Rechnungsimport ';
  100.                 if (count($result) > 1) {
  101.                     $message .=
  102.                         'sind ' count($result) . ' Fehler aufgetreten.';
  103.                 } else {
  104.                     $message .= 'ist ein Fehler aufgetreten.';
  105.                 }
  106.                 $this->addFlash('error'$message);
  107.                 foreach ($result as $key => $error) {
  108.                     $this->addFlash('error'$key '. ' $error);
  109.                 }
  110.             } elseif ($result !== false) {
  111.                 $this->addFlash('notice'$result ' Rechnungen importiert.');
  112.                 return $this->redirectToRoute('invoice_index');
  113.             }
  114.         }
  115.         return $this->render('invoice/index.html.twig', [
  116.             'uiService' => $uiService,
  117.             'invoices' => $invoice->getIterator(),
  118.             'total' => $invoice->count(),
  119.             'pages' => ceil($invoice->count() / self::LISTING_LIMIT),
  120.             'page' => 1,
  121.             'form' => $form->createView(),
  122.             'filterAction' => $requestStack->getSession()->get('filter'),
  123.             'env' => $_ENV,
  124.             'now' => new \DateTime()
  125.         ]);
  126.     }
  127.     /**
  128.      * @Route("/{page}/{orderby}/{order}", name="invoice_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
  129.      */
  130.     public function indexListing(
  131.         InvoiceRepository $invoiceRepo,
  132.         UiService $uiService,
  133.         $page,
  134.         $orderby,
  135.         $order,
  136.         RequestStack $requestStack
  137.     ): Response {
  138.         $uiService->storeSortOrder('invoice-index-listing'$orderby$order);
  139.         $invoice $invoiceRepo->getByClientPaged(
  140.             $this->getCurrentClient(),
  141.             self::LISTING_LIMIT,
  142.             $order,
  143.             $orderby,
  144.             $page,
  145.             $requestStack->getSession()->get('filter')
  146.         );
  147.         return $this->render('invoice/_index_listing.html.twig', [
  148.             'invoices' => $invoice->getIterator(),
  149.             'total' => $invoice->count(),
  150.             'pages' => ceil($invoice->count() / self::LISTING_LIMIT),
  151.             'page' => $page,
  152.             'filterAction' => $requestStack->getSession()->get('filter'),
  153.             'env' => $_ENV,
  154.             'now' => new \DateTime()
  155.         ]);
  156.     }
  157.     /**
  158.      * @Route("/{id}/close", name="invoice_close", methods="GET", requirements={"id"="\d+"})
  159.      */
  160.     public function close(
  161.         Request $request,
  162.         Invoice $invoice,
  163.         PdfService $pdfService,
  164.         MailerService $mailer,
  165.         EmailHistoryService $emailHistoryService
  166.     ): Response {
  167.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  168.         $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  169.      
  170.         $sentMessage $mailer->sendInvoiceEmail(
  171.             $invoice,
  172.             'Rechnung-' $invoice->getNumber() . '.pdf',
  173.             $pdf->Output('S''Rechnung-' $invoice->getNumber() . '.pdf')
  174.         );
  175.         $outputfile $this->generateUniqueFileName() . '.pdf';
  176.         $outputpath $this->getParameter('attachment_directory') . '/' $outputfile;
  177.         $pdf->Output('F'$outputpath);
  178.         $emailHistoryService->saveProtocolEntryFromInvoiceMessage(
  179.             $invoice,
  180.             $sentMessage['sender'],
  181.             $sentMessage['subject'],
  182.             $sentMessage['message'],
  183.             $outputfile,
  184.             'Rechnung-' $invoice->getNumber() . '.pdf'
  185.         );
  186.         if ($invoice->getStatus() != Invoice::STATUS_CLOSED) {
  187.             if ($invoice->isPaymentDebit()) {
  188.                 $invoice->setStatus(Invoice::STATUS_DEBIT_PENDING);
  189.             } else {
  190.                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  191.             }
  192.         }
  193.         $em $this->getDoctrine()->getManager();
  194.         //Update the order status
  195.         $newOrderState $invoice->getOrder()->setStatus(Order::STATUS_DONE);
  196.         $em->persist($newOrderState);
  197.         $em->flush();
  198.         $this->addFlash('notice''Rechnung versendet');
  199.         return $this->redirect($request->get('return'));
  200.     }
  201.     /**
  202.      * @Route("/{id}/lock", name="invoice_lock", methods="GET", requirements={"id"="\d+"})
  203.      */
  204.     public function lock(
  205.         Request $request,
  206.         Invoice $invoice,
  207.         PdfService $pdfService,
  208.       
  209.         
  210.     ): Response {
  211.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  212.         $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  213.      
  214.         $outputfile $this->generateUniqueFileName() . '.pdf';
  215.         $outputpath $this->getParameter('attachment_directory') . '/' $outputfile;
  216.         $pdf->Output('F'$outputpath);
  217.        
  218.         if ($invoice->getStatus() != Invoice::STATUS_CLOSED) {
  219.             if ($invoice->isPaymentDebit()) {
  220.                 $invoice->setStatus(Invoice::STATUS_DEBIT_PENDING);
  221.             } else {
  222.                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  223.             }
  224.         }
  225.         $em $this->getDoctrine()->getManager();
  226.         //Update the order status
  227.         $newOrderState $invoice->getOrder()->setStatus(Order::STATUS_DONE);
  228.         $em->persist($newOrderState);
  229.         $em->flush();
  230.         $this->addFlash('notice''Rechnung abgeschlossen');
  231.         return $this->redirect($request->get('return'));
  232.     }
  233.     /**
  234.      * @Route("/new/{return}", name="invoice_new", methods="GET|POST")
  235.      */
  236.     public function new(
  237.         Request $request,
  238.         $return '',
  239.         PersonRepository $personRepo,
  240.         ConfigurationService $configService
  241.     ): Response {
  242.         $customer null;
  243.         if ($return) {
  244.             $customer $personRepo->find($return);
  245.         }
  246.         $invoice = new Invoice();
  247.         $form $this->createForm(InvoiceType::class, $invoice, [
  248.             'client' => $this->getCurrentClient(),
  249.             'taxes' => $configService->getTaxConfigbyClient(
  250.                 $this->getCurrentClient()
  251.             ),
  252.             'customer' => $customer,
  253.         ]);
  254.         $form->handleRequest($request);
  255.         // check if creation is possible
  256.         if ($form->isSubmitted() && $form->isValid()) {
  257.             $em $this->getDoctrine()->getManager();
  258.             $allItemsBookable true;
  259.             $occurrences = [];
  260.             foreach ($invoice->getOrder()->getOrderItems() as $orderItem) {
  261.                 if ($orderItem->getCourseOccurrence()) {
  262.                     $occurrence $orderItem->getCourseOccurrence();
  263.                     if (
  264.                         !$occurrence->isBookable($orderItem->getQuantity()) &&
  265.                         $occurrence->getReservationAllowed()
  266.                     ) {
  267.                         $waitItem WaitItem::fromOrderItem($orderItem);
  268.                         foreach ($orderItem->getParticipants()
  269.                             as $participant) {
  270.                             $orderItem->removeParticipant($participant);
  271.                         }
  272.                         $invoice->getOrder()->addWaitItem($waitItem);
  273.                         $invoice->getOrder()->removeOrderItem($orderItem);
  274.                         $em->persist($waitItem);
  275.                         $this->addFlash(
  276.                             'error',
  277.                             'Im Kurs "' .
  278.                                 $occurrence->getTitle() .
  279.                                 '" sind nicht mehr genug Plätz verfügbar. Die Buchung wurde stattdessen zur Warteliste hinzugefügt.'
  280.                         );
  281.                     } elseif (
  282.                         !$occurrence->isBookable($orderItem->getQuantity()) &&
  283.                         !$occurrence->getReservationAllowed()
  284.                     ) {
  285.                         $allItemsBookable false;
  286.                         $this->addFlash(
  287.                             'error',
  288.                             'Im Kurs "' .
  289.                                 $occurrence->getTitle() .
  290.                                 '" sind nicht mehr genug Plätz verfügbar.'
  291.                         );
  292.                     } else {
  293.                         $occurrence->bookSlots($orderItem->getQuantity());
  294.                         $occurrences[] = $occurrence;
  295.                     }
  296.                 }
  297.             }
  298.             if ($allItemsBookable) {
  299.                 if (
  300.                     count($invoice->getOrderItems()) > ||
  301.                     count($invoice->getOrder()->getWaitItems()) > 0
  302.                 ) {
  303.                     $invoice->setNumber(
  304.                         $configService->getNewInvoiceNumberByClient(
  305.                             $this->getCurrentClient()
  306.                         )
  307.                     );
  308.                     $invoice->setSignedBy($this->getCurrentUser());
  309.                     $order $invoice->getOrder();
  310.                     $order->setClient($this->getCurrentClient());
  311.                     $order->setCustomer($customer);
  312.                     $order->setCustomerData($customer);
  313.                     $order->setDate(new \DateTime());
  314.                     $order->setNumber(
  315.                         $configService->getNewOrderNumberByClient(
  316.                             $this->getCurrentClient()
  317.                         )
  318.                     );
  319.                     $em->persist($order);
  320.                     $em->persist($invoice);
  321.                     $em->flush();
  322.                     foreach ($occurrences as $occurrence) {
  323.                         $occurrence->flushBooking();
  324.                     }
  325.                 }
  326.                 $em->flush();
  327.                 if ($return) {
  328.                     return $this->redirectToRoute('customer_invoices', [
  329.                         'id' => $return,
  330.                     ]);
  331.                 } else {
  332.                     return $this->redirectToRoute('invoice_index');
  333.                 }
  334.             }
  335.         }
  336.         return $this->render('invoice/new.html.twig', [
  337.             'invoice' => $invoice,
  338.             'form' => $form->createView(),
  339.             'customer' => $customer,
  340.         ]);
  341.     }
  342.     /**
  343.      * @Route("/{id}", name="invoice_show", methods="GET|POST", requirements={"id"="\d+"})
  344.      */
  345.     public function show(
  346.         Request $request,
  347.         Invoice $invoice,
  348.         InvoicePaymentRepository $invoicePaymentRepo,
  349.         InvoiceRepository $repo,
  350.         ConfigurationService $configService,
  351.         InvoiceService $invoiceService,
  352.         PersonRepository $personRepo
  353.     ): Response {
  354.         
  355.         $invoiceRecipient null;
  356.         if ($request->query->has('invoice')) {
  357.             //Entries from the invoice table
  358.             $invoiceRecipient $repo->findOneBy([
  359.                 'invoiceAdressPerson' => $personRepo,
  360.                 'id' => $request->get('invoice')
  361.             ]);
  362.         }
  363.         
  364.         $payments $invoicePaymentRepo->getByInvoicePaged($invoice, static::LISTING_LIMIT);
  365.         $invoiceRecipientMembers null;
  366.         $adressChanged false;
  367.         //Need the original recipient ID before update
  368.         $lastInvoiceRecipient $invoice->getInvoiceAdressPerson();
  369.         //var_dump($invoice);
  370.         if (is_null($invoice->getInvoiceAdressPerson()) ) {
  371.             if (!is_null($invoice->getInvoiceAdressPerson())) {
  372.                 $currentRecipient $invoice->getInvoiceAdressPerson();
  373.                 $invoiceRecipientMembers $personRepo->getInvoiceReciepientMembers$currentRecipient );
  374.                 /**
  375.                  * If there are no Members, so we have to look, if the current Invoice Recipient
  376.                  * is an family member. Then we can get the original client and his recipient members.
  377.                  */
  378.                 if (empty($invoiceRecipientMembers)) {
  379.                     //Get FamilyMembers By Client
  380.                     $invoiceRecipientMembers $personRepo->getInvoiceReciepientsByParent(
  381.                         $currentRecipient->getFamilyMemberOf()
  382.                     );
  383.                     //Client of the Family Member
  384.                     $currentRecipient $currentRecipient->getFamilyMemberOf();
  385.                 }
  386.                 //Create values for the SelectBox (Frontend invoice/edit)
  387.                 $invoiceRecipient $this->createInvoiceRecipientValues(
  388.                     $invoiceRecipientMembers,
  389.                     $currentRecipient,
  390.                     $invoice->getInvoiceAdressPerson()
  391.                 );
  392.             } else {
  393.                 //If there is no InvoiceAdressPerson, we have to take the Person from the Order Table.
  394.             
  395.                 $currentRecipient $invoice->getOrder()->getCustomer();
  396.                 $invoiceRecipientMembers $personRepo->getInvoiceReciepientMembers(
  397.                     $currentRecipient
  398.                 );
  399.                 //Create values for the SelectBox (Frontend invoice/edit)
  400.                 $invoiceRecipient $this->createInvoiceRecipientValues(
  401.                     $invoiceRecipientMembers,
  402.                     $currentRecipient,
  403.                     $invoice->getInvoiceAdressPerson(),
  404.                     true
  405.                 );
  406.             }
  407.         
  408.             
  409.         if (
  410.             $invoice->getInvoiceAdressPerson()
  411.             // && $invoice->getInvoiceAdressPerson()->getIsInvoiceRecipient()
  412.         ) {
  413.             $adressChanged $invoiceService->checkIfAdressHasChanged($invoicetrue);
  414.         }
  415.         // else {
  416.         //     $adressChanged = $invoiceService->checkIfAdressHasChanged($invoice, true);
  417.         // }
  418.         }
  419.         if ($request->get('flashMessage')){ $this->addFlash('notice''Rechnungsadresse wurde erfolgreich aktualisiert.');}
  420.         $cancellations $repo->findCancellationByInvoice($invoice);
  421.         if ($invoice->isDraft()) {
  422.             $currentRecipient $invoice->getInvoiceAdressPerson();
  423.             $invoiceRecipientMembers $personRepo->getInvoiceReciepientMembers$currentRecipient );
  424.             $invoiceRecipient $this->createInvoiceRecipientValues(
  425.                 $invoiceRecipientMembers,
  426.                 $currentRecipient,
  427.                 $invoice->getInvoiceAdressPerson()
  428.             );
  429.         //  var_dump($invoiceRecipient);
  430.             $form $this->createForm(InvoiceOnlyType::class, $invoice, [
  431.                 'client' => $this->getCurrentClient(),
  432.                 'taxes' => $configService->getTaxConfigbyClient(
  433.                     $this->getCurrentClient()
  434.                 ),
  435.                 'invoiceRecipient' => $invoiceRecipient,
  436.                 
  437.             ]);
  438.             $form->handleRequest($request);
  439.             if ($form->isSubmitted() && $form->isValid()) {
  440.                 $em $this->getDoctrine()->getManager();
  441.                
  442.                     $em->flush();
  443.                
  444.                 $this->addFlash('notice''Rechnung gespeichert.');
  445.             }
  446.             return $this->render('invoice/edit.html.twig', [
  447.                 'invoice' => $invoice,
  448.                 'cancellations' => $cancellations,
  449.                 'payments' => $payments->getIterator(),
  450.                 'total' => $payments->count(),
  451.                 'pages' => ceil($payments->count() / self::LISTING_LIMIT),
  452.                 'page' => 1,
  453.                 'form' => $form->createView(),
  454.                 'adressChanged' => $adressChanged,
  455.             ]);
  456.         } else {
  457.             return $this->render('invoice/show.html.twig', [
  458.                 'invoice' => $invoice,
  459.                 'cancellations' => $cancellations,
  460.                 'payments' => $payments->getIterator(),
  461.                 'total' => $payments->count(),
  462.                 'pages' => ceil($payments->count() / self::LISTING_LIMIT),
  463.                 'page' => 1,
  464.             ]);
  465.         }
  466.     }
  467.     /**
  468.      * @Route("/{id}/updateAdress", name="invoice_update_adress", methods="GET|POST", requirements={"id"="\d+"})
  469.      */
  470.     public function updateAdress(
  471.         Request $request,
  472.         Invoice $invoice,
  473.         InvoiceService $invoiceService,
  474.         PersonRepository $personRepo
  475.     ): RedirectResponse {
  476.         $em $this->getDoctrine()->getManager();
  477.         if ($request->get('person')) {
  478.             $person $personRepo->find($request->get('personId'));
  479.             $updatedInvoice $invoiceService->updateInvoiceAdress($invoice$person);
  480.             $em->persist($updatedInvoice);
  481.             $em->flush();
  482.         }
  483.         // else {
  484.         //     $updatedInvoice = $invoiceService->updateInvoiceAdress($invoice, $null);
  485.         // }
  486.         return $this->redirectToRoute('invoice_show', [
  487.             'id' => $invoice->getId(),
  488.             'flashMessage' => true
  489.         ]);
  490.     }
  491.     /**
  492.      * @Route("/{id}", name="invoice_delete", methods="DELETE", requirements={"id"="\d+"})
  493.      */
  494.     public function delete(Request $requestInvoice $invoiceInvoiceItemAttendeesRepository $invoiceItemAttendeesRepo): Response
  495.     {
  496.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  497.         if ($this->isCsrfTokenValid('delete' $invoice->getId(), $request->request->get('_token')) && $invoice->isDraft()) {
  498.             $em $this->getDoctrine()->getManager();
  499.             $attendees = [];
  500.             foreach ($invoice->getItems() as $item) {
  501.                 $attendees $invoiceItemAttendeesRepo->findBy(['invoice_item' => $item]);
  502.             }
  503.             if ($attendees) {
  504.                 foreach ($attendees as $attendee) {
  505.                     $em->remove($attendee);
  506.                 }
  507.             }
  508.             $em->remove($invoice);
  509.             $em->flush();
  510.             $this->addFlash('notice''Rechnung gelöscht');
  511.         }
  512.         return $this->redirectToRoute('invoice_index');
  513.     }
  514.     /**
  515.      * @Route("/{id}/cancel", name="invoice_cancel", methods="POST", requirements={"id"="\d+"})
  516.      */
  517.     public function cancel(
  518.         Request $request,
  519.         Invoice $invoice,
  520.         ConfigurationService $configService
  521.         InvoiceItemAttendeesRepository $invoiceItemAttendeesRepo
  522.     ): Response {
  523.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  524.         if ($this->isCsrfTokenValid('cancel' $invoice->getId(), $request->request->get('_token')) && !$invoice->isDraft()) {
  525.             $em $this->getDoctrine()->getManager();
  526.             $coppiedInvoice $invoice->cloneForCancellation();
  527.             $cancellation $coppiedInvoice['invoice'];
  528.             $cancellation->setInvoiceDate(new \DateTime());
  529.             $cancellation->setNumber(
  530.                 $configService->getNewInvoiceNumberByClient(
  531.                     $this->getCurrentClient()
  532.                 )
  533.             );
  534.             $cancellation->setCancellation(true);
  535.             $cancellation->setParent($invoice);
  536.             $cancellation->setSignedBy($this->getCurrentUser());
  537.             $cancellation->setStatus(Invoice::STATUS_CLOSED);
  538.             $invoice->setCancelled(true);
  539.             foreach ($coppiedInvoice['attendees'] as $attendee) {
  540.                 $em->persist($attendee);
  541.             }
  542.             $em->persist($cancellation);
  543.             $em->flush();
  544.             $this->addFlash('notice''Rechnung storniert');
  545.         }
  546.         if ($this->isCsrfTokenValid('cancel' $invoice->getId(), $request->request->get('_token')) && $invoice->isDraft()) {
  547.             $em $this->getDoctrine()->getManager();
  548.             $attendees = [];
  549.             foreach ($invoice->getItems() as $item) {
  550.                 $attendees $invoiceItemAttendeesRepo->findBy(['invoice_item' => $item]);
  551.             }
  552.             if ($attendees) {
  553.                 foreach ($attendees as $attendee) {
  554.                     $em->remove($attendee);
  555.                 }
  556.             }
  557.             $em->remove($invoice);
  558.             $em->flush();
  559.             $this->addFlash('notice''Rechnung gelöscht');
  560.         }
  561.         return $this->redirectToRoute('invoice_show', [
  562.             'id' => $invoice->getId(),
  563.         ]);
  564.     }
  565.     /**
  566.      * @Route("/{id}/cancel_fromorder/{order}", name="invoice_cancel_fromorder", methods="POST", requirements={"id"="\d+"})
  567.      */
  568.     public function cancel_fromorder(
  569.         Request $request,
  570.         Invoice $invoice,
  571.         Order $order,
  572.         InvoiceItemAttendeesRepository $invoiceItemAttendeesRepo,
  573.         ConfigurationService $configService
  574.     ): Response {
  575.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  576.         if ($this->isCsrfTokenValid('cancel' $invoice->getId(), $request->request->get('_token')) && !$invoice->isDraft()) {
  577.             $em $this->getDoctrine()->getManager();
  578.             $coppiedInvoice $invoice->cloneForCancellation();
  579.             $cancellation $coppiedInvoice['invoice'];
  580.             $cancellation->setInvoiceDate(new \DateTime());
  581.             $cancellation->setNumber(
  582.                 $configService->getNewInvoiceNumberByClient(
  583.                     $this->getCurrentClient()
  584.                 )
  585.             );
  586.             $cancellation->setCancellation(true);
  587.             $cancellation->setParent($invoice);
  588.             $cancellation->setSignedBy($this->getCurrentUser());
  589.             $cancellation->setStatus(Invoice::STATUS_CLOSED);
  590.             $invoice->setCancelled(true);
  591.             foreach ($coppiedInvoice['attendees'] as $attendee) {
  592.                 $em->persist($attendee);
  593.             }
  594.             $em->persist($cancellation);
  595.             $em->flush();
  596.             $this->addFlash('notice''Rechnung storniert');
  597.         }
  598.          if ($this->isCsrfTokenValid('cancel' $invoice->getId(), $request->request->get('_token')) && $invoice->isDraft()) {
  599.             $em $this->getDoctrine()->getManager();
  600.             $attendees = [];
  601.             foreach ($invoice->getItems() as $item) {
  602.                 $attendees $invoiceItemAttendeesRepo->findBy(['invoice_item' => $item]);
  603.             }
  604.             if ($attendees) {
  605.                 foreach ($attendees as $attendee) {
  606.                     $em->remove($attendee);
  607.                 }
  608.             }
  609.             $em->remove($invoice);
  610.             $em->flush();
  611.             $this->addFlash('notice''Rechnung gelöscht');
  612.         }
  613.         return $this->redirectToRoute('order_show', [
  614.             'id' => $order->getId(),
  615.         ]);
  616.     }
  617.     /**
  618.      * @Route("/{id}/pdf", name="invoice_pdf", methods="GET", requirements={"id"="\d+"})
  619.      */
  620.     public function pdf(
  621.         Request $request,
  622.         Invoice $invoice,
  623.         ConfigurationService $configService,
  624.         PdfService $pdfService,
  625.         InvoiceItemAttendeesRepository $invoiceItemAttendeesRepository
  626.     ) {
  627.         #dd($invoice->getItems()[0]->getId());
  628.         #        dd(count($invoice->getItems()));
  629.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  630.         $pdf $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
  631.         $pdf->Output('D''Rechnung-' $invoice->getNumber() . '.pdf');
  632.         exit();
  633.     }
  634.     /**
  635.      * @Route("/{id}/cancellation-pdf", name="invoice_cancellation-pdf", methods="GET", requirements={"id"="\d+"})
  636.      */
  637.     public function cancellationPdf(
  638.         Request $request,
  639.         Invoice $invoice,
  640.         ConfigurationService $configService,
  641.         PdfService $pdfService
  642.     ) {
  643.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  644.         $pdf $pdfService->getCancellationPdf(
  645.             $this->getCurrentClient(),
  646.             $invoice
  647.         );
  648.         $pdf->Output('D''Gutschrift-' $invoice->getNumber() . '.pdf');
  649.         exit();
  650.     }
  651.     /**
  652.      * @Route("/{id}/sepa-xml", name="invoice_sepa-xml", methods="GET", requirements={"id"="\d+"})
  653.      */
  654.     public function sepaXml(
  655.         Request $request,
  656.         Invoice $invoice,
  657.         ConfigurationService $configService,
  658.         SepaXmlService $sepaXmlService
  659.     ) {
  660.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  661.         $em $this->getDoctrine()->getManager();
  662.         $invoice->setStatus(Invoice::STATUS_CLOSED);
  663.         if (
  664.             !$invoice
  665.                 ->getOrder()
  666.                 ->getCustomer()
  667.                 ->getDebitActive()
  668.         ) {
  669.             $invoice
  670.                 ->getOrder()
  671.                 ->getCustomer()
  672.                 ->setDebitActive(true);
  673.             $invoice->setIsNewSepaMandate(true);
  674.         }
  675.         $config $configService->getSepaXmlConfigByClient(
  676.             $this->getCurrentClient()
  677.         );
  678.         try {
  679.             $xml $sepaXmlService->getSepaXmlSingle(
  680.                 $this->getCurrentClient(),
  681.                 $config,
  682.                 $invoice
  683.             );
  684.         } catch (ServiceException $e) {
  685.             $this->addFlash('error'$e->getMessage());
  686.             return $this->redirectToRoute('invoice_index');
  687.         }
  688.         $em->flush();
  689.         $response = new Response($xml);
  690.         $response->headers->set('Content-Type''text/xml');
  691.         $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  692.         return $response;
  693.     }
  694.     /**
  695.      * @Route("/new-sepa-xml", name="invoice_new-sepa-xml", methods="GET")
  696.      */
  697.     public function newInvoicesSepaXml(
  698.         Request $request,
  699.         ConfigurationService $configService,
  700.         SepaXmlService $sepaXmlService,
  701.         InvoiceRepository $invoiceRepo
  702.     ) {
  703.         $invoices $invoiceRepo->getByClientAndStatuses(
  704.             $this->getCurrentClient(),
  705.             [Invoice::STATUS_DRAFTInvoice::STATUS_DEBIT_PENDING],
  706.             Invoice::PAYMENT_DEBIT
  707.         );
  708.         $invoicesToExport = new ArrayCollection();
  709.         foreach ($invoices as $invoice) {
  710.             if (!$invoicesToExport->contains($invoice)) {
  711.                 $invoice->setStatus(Invoice::STATUS_CLOSED);
  712.                 $invoicesToExport->add($invoice);
  713.                 if (
  714.                     $invoice->getOrder()->getCustomer() &&
  715.                     !$invoice
  716.                         ->getOrder()
  717.                         ->getCustomer()
  718.                         ->getDebitActive()
  719.                 ) {
  720.                     $invoice
  721.                         ->getOrder()
  722.                         ->getCustomer()
  723.                         ->setDebitActive(true);
  724.                     $invoice->setIsNewSepaMandate(true);
  725.                 }
  726.             }
  727.         }
  728.         try {
  729.             if (count($invoicesToExport) > 0) {
  730.                 $config $configService->getSepaXmlConfigByClient($this->getCurrentClient());
  731.                 $xml $sepaXmlService->getSepaXmlMultiple($this->getCurrentClient(), $config$invoicesToExport);
  732.                 $em $this->getDoctrine()->getManager();
  733.                 $em->flush();
  734.                 $response = new Response($xml);
  735.                 $response->headers->set('Content-Type''text/xml');
  736.                 $response->headers->set('Content-disposition''attachment; filename="SEPA-' date('Ymd-His') . '.xml"');
  737.                 return $response;
  738.             }
  739.         } catch (ServiceException $e) {
  740.             $this->addFlash('error'$e->getMessage());
  741.             return $this->redirectToRoute('invoice_index');
  742.         }
  743.         $this->addFlash('error''Es wurden keine exportierbaren Rechnungen gefunden.');
  744.         return $this->redirectToRoute('invoice_index');
  745.     }
  746.     /**
  747.      * @Route("/{id}/payments/{page}/{orderby}/{order}", name="invoice_payments_listing", methods="GET", requirements={"id"="\d+"})
  748.      */
  749.     public function paymentsListing(
  750.         Request $request,
  751.         Invoice $invoice,
  752.         $page 1,
  753.         $orderby 'payedDate',
  754.         $order 'ASC',
  755.         InvoicePaymentRepository $repo
  756.     ) {
  757.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  758.         $payments $repo->getByInvoicePaged(
  759.             $invoice,
  760.             self::LISTING_LIMIT,
  761.             $order,
  762.             $orderby,
  763.             $page
  764.         );
  765.         return $this->render('invoice/tabs/_payments_listing.html.twig', [
  766.             'payments' => $payments->getIterator(),
  767.             'total' => $payments->count(),
  768.             'pages' => ceil($payments->count() / self::LISTING_LIMIT),
  769.             'page' => $page,
  770.         ]);
  771.     }
  772.     /**
  773.      * @Route("/{id}/reminders/{page}/{orderby}/{order}", name="invoice_reminders_listing", methods="GET", requirements={"id"="\d+"})
  774.      */
  775.     public function remindersListing(
  776.         Request $request,
  777.         Invoice $invoice,
  778.         $page 1,
  779.         $orderby 'remindDate',
  780.         $order 'ASC',
  781.         InvoiceReminderRepository $repo
  782.     ) {
  783.         $this->denyAccessUnlessGranted('ROLE_MANAGER'$invoice);
  784.         $reminders $repo->getByInvoicePaged(
  785.             $invoice,
  786.             self::LISTING_LIMIT,
  787.             $order,
  788.             $orderby,
  789.             $page
  790.         );
  791.         return $this->render('invoice/tabs/_reminders_listing.html.twig', [
  792.             'reminders' => $reminders->getIterator(),
  793.             'total' => $reminders->count(),
  794.             'pages' => ceil($reminders->count() / self::LISTING_LIMIT),
  795.             'page' => $page,
  796.         ]);
  797.     }
  798.     private function getInvoiceRecipientId(Person $person)
  799.     {
  800.         if ($person->getIsInvoiceRecipient()) {
  801.             return [
  802.                 'id' => $person->getId(),
  803.                 'type' => 'personRecipient'
  804.             ];
  805.         }
  806.         return [
  807.             'id' => $person->getId(),
  808.             'type' => 'clientRecipient'
  809.         ];
  810.     }
  811.     private function createInvoiceRecipientValues($invoiceRecipientMembers$currentRecipient$invoicePerson null$onlyClient false)
  812.     {
  813.         $res = [];
  814.         $invoicePersonId null;
  815.         if ($invoicePerson) {
  816.             $res[] = $invoicePerson;
  817.             $invoicePersonId $invoicePerson->getId();
  818.         }
  819.         if ($onlyClient) {
  820.             $res[] = $currentRecipient;
  821.         } else {
  822.             if (
  823.                 $currentRecipient &&
  824.                 $currentRecipient->getId() != $invoicePersonId
  825.             $res[] = $currentRecipient;
  826.         }
  827.         foreach ($invoiceRecipientMembers as $person) {
  828.             if ($person->getId() != $invoicePersonId) {
  829.                 $res[] = $person;
  830.             }
  831.         }
  832.         return $res;
  833.     }
  834.     /**
  835.      * @Route("/{id}/getPersonAdress", name="get_person_adress", methods="GET|POST")
  836.      */
  837.     public  function getClientAdress(Request $requestPerson $personInvoiceRepository $invoiceRepo)
  838.     {
  839.         /**
  840.          * Ajax Call
  841.          * Returns the person informations back to the invoice/edit by onChange the persons.
  842.          */
  843.         $invoiceRecipient null;
  844.         if ($request->query->has('invoice')) {
  845.             //Entries from the invoice table
  846.             $invoiceRecipient $invoiceRepo->findOneBy([
  847.                 'invoiceAdressPerson' => $person,
  848.                 'id' => $request->get('invoice')
  849.             ]);
  850.         }
  851.         if ($invoiceRecipient) {
  852.             return $this->json([
  853.                 'person' => [
  854.                     'id' => $person->getId(),
  855.                     'company' => $invoiceRecipient->getCompany(),
  856.                     'name' => $invoiceRecipient->getInvoiceFullname(),
  857.                     'street' => $invoiceRecipient->getInvoiceFullStreet(),
  858.                     'place' => $invoiceRecipient->getInvoicePostalcodeCity(),
  859.                     'isInvoiceRecipient' => $person->getIsInvoiceRecipient()
  860.                 ]
  861.             ], Response::HTTP_OK);
  862.         }
  863.         //Entries from the person table
  864.         return $this->json([
  865.             'person' => [
  866.                 'id' => $person->getId(),
  867.                 'company' => $person->getCompany(),
  868.                 'name' => $person->getFullname(),
  869.                 'street' => $person->getFullStreet(),
  870.                 'place' => $person->getPostalcodeCity(),
  871.                 'isInvoiceRecipient' => $person->getIsInvoiceRecipient()
  872.             ]
  873.         ], Response::HTTP_OK);
  874.     }
  875.     private function checkForUnsetInvoiceStatus(
  876.         InvoiceRepository $invoiceRepo,
  877.         PaymentService $paymentService
  878.     ) {
  879.         $allInvoicesWithoutState $invoiceRepo->findBy(['paymentStatus' => null]);
  880.         if (!empty($allInvoicesWithoutState)) {
  881.             foreach ($allInvoicesWithoutState as $invoice) {
  882.                 $sumOfPayments $paymentService->getPayments($invoice);
  883.                 $state $paymentService->interpretPayments($sumOfPayments$invoice);
  884.                 $invoice->setPaymentStatus($state);
  885.                 $em $this->getDoctrine()->getManager();
  886.                 $em->persist($invoice);
  887.             }
  888.             $em->flush();
  889.         }
  890.     }
  891.     /**
  892.      * @Route("/{id}/payInvoice", name="pay_invoice", methods="GET|POST")
  893.      */
  894.     public function payTheBill(Invoice $invoicePaymentService $paymentService)
  895.     {
  896.         $openSum = (float) $paymentService->payAmount($invoice);
  897.         $invoicePayment = new InvoicePayment();
  898.         $invoicePayment->setInvoice($invoice);
  899.         $invoicePayment->setPayedDate(new \DateTime());
  900.         $invoicePayment->setSum($openSum);
  901.         $invoice->setPaymentStatus(Invoice::FULLY_PAID);
  902.         $em $this->getDoctrine()->getManager();
  903.         $em->persist($invoicePayment);
  904.         $em->persist($invoice);
  905.         $em->flush();
  906.         return $this->json([
  907.             'success' => "Die Rechnung wurde als bezahlt markiert.",
  908.             'invoice' => true,
  909.         ]);
  910.     }
  911. }