diff --git a/app/config/packages/backoffice_menu.yaml b/app/config/packages/backoffice_menu.yaml index 93693493d..73abfde72 100644 --- a/app/config/packages/backoffice_menu.yaml +++ b/app/config/packages/backoffice_menu.yaml @@ -167,9 +167,12 @@ parameters: - admin_event_prices - admin_event_prices_add - admin_event_prices_edit - forum_facturation: + admin_event_factures: nom: "Factures d'évènement" niveau: 'ROLE_ADMIN' + url: '/admin/event/invoices' + extra_routes: + - admin_event_factures talks: nom: 'Conférences' niveau: 'ROLE_FORUM' diff --git a/app/config/routing/admin_event.yml b/app/config/routing/admin_event.yml index fee64e9ab..f98440211 100644 --- a/app/config/routing/admin_event.yml +++ b/app/config/routing/admin_event.yml @@ -82,6 +82,30 @@ admin_event_prices_edit: event: \d+ id: \d+ +admin_event_factures: + path: /invoices + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\ListFacturesAction } + +admin_event_factures_download_facture: + path: /invoices/download/invoice + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\DownloadFactureAction } + +admin_event_factures_download_devis: + path: /invoices/download/quotation + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\DownloadDevisAction } + +admin_event_factures_issue_facture: + path: /invoices/issue/invoice + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\IssueFactureAction } + +admin_event_factures_send_facture: + path: /invoices/send/invoice + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\SendFactureAction } + +admin_event_factures_delete_facture: + path: /invoices/delete/invoice/{token} + defaults: {_controller: AppBundle\Controller\Admin\Event\Facturation\DeleteFactureAction } + admin_event_speaker_infos: path: /speaker-infos defaults: {_controller: AppBundle\Controller\Admin\Event\SpeakerInfosAction } diff --git a/htdocs/templates/administration/forum_facturation.html b/htdocs/templates/administration/forum_facturation.html index afba099ea..046352bc0 100644 --- a/htdocs/templates/administration/forum_facturation.html +++ b/htdocs/templates/administration/forum_facturation.html @@ -127,17 +127,17 @@

Factures d'évènement

{literal} {/literal} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php new file mode 100644 index 000000000..dc9fc8239 --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php @@ -0,0 +1,52 @@ +csrfTokenManager->isTokenValid(new CsrfToken('event_invoice_delete', $token))) { + $this->addFlash('error', 'Token invalide'); + return $this->redirectToRoute('admin_event_factures'); + } + + $reference = $request->query->get('ref'); + $facture = $this->invoiceRepository->getByReference($reference); + if (!$facture instanceof Invoice) { + throw new NotFoundHttpException("Cette facture n'existe pas"); + } + + try { + $this->invoiceService->deleteInvoice($facture); + $this->audit->log('Supprimer => facture n°' . $reference); + $this->addFlash('notice', 'La facture est supprimée'); + return $this->redirectToRoute('admin_event_factures'); + } catch (Exception) { + } + + $this->addFlash('error', "La facture n'a pas pu être supprimée"); + return $this->redirectToRoute('admin_event_factures'); + } +} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php new file mode 100644 index 000000000..c115ebd3f --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php @@ -0,0 +1,39 @@ +query->get('ref'); + $devis = $this->invoiceRepository->getByReference($reference); + if (!$devis instanceof Invoice) { + throw new NotFoundHttpException("Ce devis n'existe pas"); + } + + ob_start(); + $this->facturation->genererDevis($reference); + $pdf = ob_get_clean(); + + $response = new Response($pdf); + $response->headers->set('Content-Type', 'application/pdf'); + + return $response; + } +} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php new file mode 100644 index 000000000..8072c4bc8 --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php @@ -0,0 +1,39 @@ +query->get('ref'); + $facture = $this->invoiceRepository->getByReference($reference); + if (!$facture instanceof Invoice) { + throw new NotFoundHttpException("Cette facture n'existe pas"); + } + + ob_start(); + $this->facturation->genererFacture($reference); + $pdf = ob_get_clean(); + + $response = new Response($pdf); + $response->headers->set('Content-Type', 'application/pdf'); + + return $response; + } +} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php new file mode 100644 index 000000000..988bf4ee2 --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php @@ -0,0 +1,41 @@ +query->get('ref'); + $facture = $this->invoiceRepository->getByReference($reference); + if (!$facture instanceof Invoice) { + throw new NotFoundHttpException("Cette facture n'existe pas"); + } + + if ($this->facturation->estFacture($reference)) { + $this->audit->log('Facturation => facture n°' . $reference); + $this->addFlash('notice', 'La facture est prise en compte'); + return $this->redirectToRoute('admin_event_factures'); + } + + $this->addFlash('error', "La facture n'a pas pu être prise en compte"); + return $this->redirectToRoute('admin_event_factures'); + } +} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php new file mode 100644 index 000000000..68f21892c --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php @@ -0,0 +1,40 @@ +event; + $sort = $request->query->get('sort', 'date_facture'); + $direction = $request->query->get('direction', 'desc'); + Assert::inArray($sort, self::VALID_SORTS); + Assert::inArray($direction, self::VALID_DIRECTIONS); + $filter = $request->query->get('filter', ''); + $invoices = $this->invoiceRepository->getByEventId($event->getId(), $sort, $direction, $filter); + + return $this->render('admin/event/facturation/list.html.twig', [ + 'event' => $event, + 'event_select_form' => $eventSelection->selectForm(), + 'direction' => $direction, + 'invoices' => $invoices, + 'sort' => $sort, + 'filter' => $filter, + ]); + } +} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php new file mode 100644 index 000000000..b2ebfd326 --- /dev/null +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php @@ -0,0 +1,41 @@ +query->get('ref'); + $devis = $this->invoiceRepository->getByReference($reference); + if (!$devis instanceof Invoice) { + throw new NotFoundHttpException("Cette facture n'existe pas"); + } + + if ($this->facturation->envoyerFacture($reference)) { + $this->audit->log('Facturation => facture n°' . $reference); + $this->addFlash('notice', 'La facture a été envoyée'); + return $this->redirectToRoute('admin_event_factures'); + } + + $this->addFlash('error', "La facture n'a pas pu être envoyée"); + return $this->redirectToRoute('admin_event_factures'); + } +} diff --git a/sources/AppBundle/Event/Model/Repository/EventRepository.php b/sources/AppBundle/Event/Model/Repository/EventRepository.php index 00e0343c2..9c18a1696 100644 --- a/sources/AppBundle/Event/Model/Repository/EventRepository.php +++ b/sources/AppBundle/Event/Model/Repository/EventRepository.php @@ -84,6 +84,15 @@ public function getLastEvent() return $query->query($this->getCollection(new HydratorSingleObject()))->first(); } + public function getMostRecentEvent(): ?Event + { + $query = $this + ->getQuery('SELECT id, path, titre, text, date_debut, date_fin, date_fin_appel_conferencier, date_fin_vente FROM afup_forum ORDER BY date_debut DESC') + ; + + return $query->query($this->getCollection(new HydratorSingleObject()))->first(); + } + public function getNextEventForGithubUser(GithubUser $githubUser) { $events = $this @@ -280,6 +289,13 @@ public function getAllActive(): CollectionInterface return $query->query($this->getCollection(new HydratorSingleObject())); } + public function getAllSortedByTitre(): CollectionInterface + { + $query = $this->getQuery('SELECT * FROM afup_forum ORDER BY titre ASC'); + + return $query->query($this->getCollection(new HydratorSingleObject())); + } + public static function initMetadata(SerializerFactoryInterface $serializerFactory, array $options = []) { $metadata = new Metadata($serializerFactory); diff --git a/sources/AppBundle/Event/Model/Repository/InvoiceRepository.php b/sources/AppBundle/Event/Model/Repository/InvoiceRepository.php index 812f44b5d..e92f4bd3a 100644 --- a/sources/AppBundle/Event/Model/Repository/InvoiceRepository.php +++ b/sources/AppBundle/Event/Model/Repository/InvoiceRepository.php @@ -13,6 +13,7 @@ use CCMBenchmark\Ting\Driver\Mysqli\Serializer\Boolean; use CCMBenchmark\Ting\Repository\CollectionInterface; use CCMBenchmark\Ting\Repository\HydratorArray; +use CCMBenchmark\Ting\Repository\HydratorSingleObject; use CCMBenchmark\Ting\Repository\Metadata; use CCMBenchmark\Ting\Repository\MetadataInitializer; use CCMBenchmark\Ting\Repository\Repository; @@ -165,6 +166,29 @@ public function searchAllQuotesAndInvoices(string $search): CollectionInterface return $query->query($this->getCollection(new HydratorArray())); } + public function getByEventId(int $eventId, string $sort = 'date_facture', string $direction = 'desc', string $filter = ''): CollectionInterface + { + /** @var Select $builder */ + $builder = $this->getQueryBuilder(self::QUERY_SELECT); + $builder->cols(['*']) + ->from('afup_facturation_forum aff') + ->where('aff.id_forum = :event_id') + ->where( + 'aff.etat in (' . Ticket::STATUS_PAID . ', ' . Ticket::STATUS_WAITING . ', ' . Ticket::STATUS_CONFIRMED . ')', + ); + if ($filter !== '') { + $builder->where('(aff.societe LIKE :filter OR aff.reference LIKE :filter)') + ->bindValues(['filter' => '%' . $filter . '%']); + } + $builder->orderBy(["$sort $direction"]) + ->bindValues(['event_id' => $eventId]); + + return $this->getQuery($builder->getStatement()) + ->setParams($builder->getBindValues()) + ->query($this->getCollection(new HydratorSingleObject())); + } + + /** * @inheritDoc */ diff --git a/templates/admin/event/facturation/list.html.twig b/templates/admin/event/facturation/list.html.twig new file mode 100644 index 000000000..3f7d0c602 --- /dev/null +++ b/templates/admin/event/facturation/list.html.twig @@ -0,0 +1,121 @@ +{% extends 'admin/base_with_header.html.twig' %} + +{% block content %} +

Factures d'évènements

+ {% include 'admin/event/change_event.html.twig' with {form: event_select_form} only %} + +
+
+ + +
+
+
+ + +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + {% for invoice in invoices %} + + + + + + + + + + {% else %} + + + + {% endfor %} + +
Date factureRéférenceSociété / personne physiqueMontantEtatFacturation
{{ invoice.invoiceDate|format_date('short') }}{{ invoice.reference }}{% if invoice.company %}{{ invoice.company}}{% else %}{{ invoice.lastname ~ ' ' ~invoice.firstname }}{% endif %}{{ invoice.amount }} € + {% if invoice.status == 4 %} + Reglée{% if invoice.paymentDate %}
+ {{ invoice.paymentDate|format_date('short') }}{% endif %}
+ {% elseif invoice.status == 6 %} + En attente règlement + {% elseif invoice.status == 7 %} + Confirmée + {% else %} + -- + {% endif %} +
+ {% if invoice.invoice %} + Facturée + {% else %} + À facturer + {% endif %} + + + + + {% if invoice.invoice == 0 %} + + + + {% endif %} + {% if invoice.invoice == 1 %} + + + + + + + + + + + + {% endif %} +
Aucune facturation
+
+ +{% endblock %} + +