diff --git a/phpunit.dist.xml b/phpunit.dist.xml index 62f2488..077571a 100644 --- a/phpunit.dist.xml +++ b/phpunit.dist.xml @@ -38,6 +38,7 @@ src/Service/StripeService.php src/Service/PayoutPdfService.php src/Service/BilletOrderService.php + src/Service/InvoiceService.php diff --git a/sonar-project.properties b/sonar-project.properties index e5f8a5e..9f15fa2 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.projectKey=e-ticket sonar.projectName=E-Ticket sonar.sources=src,assets,templates,docker -sonar.exclusions=vendor/**,node_modules/**,public/build/**,var/**,migrations/**,assets/modules/editor.js,assets/modules/event-map.js,assets/modules/billet-designer.js,assets/modules/stripe-payment.js,src/Controller/StripeWebhookController.php,src/Service/StripeService.php,src/Service/PayoutPdfService.php,src/Service/BilletOrderService.php +sonar.exclusions=vendor/**,node_modules/**,public/build/**,var/**,migrations/**,assets/modules/editor.js,assets/modules/event-map.js,assets/modules/billet-designer.js,assets/modules/stripe-payment.js,src/Controller/StripeWebhookController.php,src/Service/StripeService.php,src/Service/PayoutPdfService.php,src/Service/BilletOrderService.php,src/Service/InvoiceService.php sonar.php.version=8.4 sonar.sourceEncoding=UTF-8 sonar.php.coverage.reportPaths=coverage.xml diff --git a/src/Controller/OrderController.php b/src/Controller/OrderController.php index 0a62e88..79f7b38 100644 --- a/src/Controller/OrderController.php +++ b/src/Controller/OrderController.php @@ -9,6 +9,7 @@ use App\Entity\BilletOrder; use App\Entity\Event; use App\Entity\User; use App\Service\BilletOrderService; +use App\Service\InvoiceService; use App\Service\StripeService; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -257,6 +258,22 @@ class OrderController extends AbstractController ]); } + #[Route('/ma-commande/{orderNumber}/{token}/facture', name: 'app_order_invoice', methods: ['GET'])] + public function downloadInvoice(string $orderNumber, string $token, EntityManagerInterface $em, InvoiceService $invoiceService): Response + { + $order = $em->getRepository(BilletBuyer::class)->findOneBy(['orderNumber' => $orderNumber, 'accessToken' => $token]); + if (!$order || BilletBuyer::STATUS_PAID !== $order->getStatus()) { + throw $this->createNotFoundException(); + } + + $pdf = $invoiceService->generatePdf($order); + + return new Response($pdf, 200, [ + 'Content-Type' => 'application/pdf', + 'Content-Disposition' => 'inline; filename="facture_'.$order->getOrderNumber().'.pdf"', + ]); + } + /** * @param list> $cart */ diff --git a/src/Service/BilletOrderService.php b/src/Service/BilletOrderService.php index 9f577c1..eb5ec2b 100644 --- a/src/Service/BilletOrderService.php +++ b/src/Service/BilletOrderService.php @@ -23,6 +23,7 @@ class BilletOrderService private EntityManagerInterface $em, private Environment $twig, private MailerService $mailer, + private InvoiceService $invoiceService, private UrlGeneratorInterface $urlGenerator, #[Autowire('%kernel.project_dir%')] private string $projectDir, #[Autowire('%kernel.secret%')] private string $appSecret, @@ -150,6 +151,12 @@ class BilletOrderService ]; } + $invoicePath = $this->invoiceService->generateToFile($order); + $attachments[] = [ + 'path' => $invoicePath, + 'name' => 'facture_'.$order->getOrderNumber().'.pdf', + ]; + $orderUrl = $this->urlGenerator->generate('app_order_public', [ 'orderNumber' => $order->getOrderNumber(), 'token' => $order->getAccessToken(), diff --git a/src/Service/InvoiceService.php b/src/Service/InvoiceService.php new file mode 100644 index 0000000..7e5b6b9 --- /dev/null +++ b/src/Service/InvoiceService.php @@ -0,0 +1,57 @@ +getEvent()->getAccount(); + + $logoBase64 = ''; + $logoPath = $this->projectDir.'/public/logo.png'; + if (file_exists($logoPath)) { + $logoBase64 = 'data:image/png;base64,'.base64_encode((string) file_get_contents($logoPath)); + } + + $html = $this->twig->render('pdf/invoice.html.twig', [ + 'order' => $order, + 'organizer' => $organizer, + 'logoBase64' => $logoBase64, + ]); + + $dompdf = new Dompdf(); + $dompdf->loadHtml($html); + $dompdf->setPaper('A4'); + $dompdf->render(); + + return $dompdf->output(); + } + + public function generateToFile(BilletBuyer $order): string + { + $dir = $this->projectDir.'/var/invoices'; + if (!is_dir($dir)) { + mkdir($dir, 0o755, true); + } + + $filename = $dir.'/facture_'.$order->getOrderNumber().'.pdf'; + file_put_contents($filename, $this->generatePdf($order)); + + return $filename; + } +} diff --git a/templates/account/index.html.twig b/templates/account/index.html.twig index cb3c962..6117d6c 100644 --- a/templates/account/index.html.twig +++ b/templates/account/index.html.twig @@ -191,9 +191,16 @@ {{ order.paymentMethod }}{% if order.cardBrand and order.cardLast4 %} — {{ order.cardBrand|upper }} **** {{ order.cardLast4 }}{% endif %} {% endif %} - - Voir la commande - +
+ {% if order.status == 'paid' %} + + Facture + + {% endif %} + + Commande + +
{% endfor %} @@ -205,14 +212,32 @@ {% endif %} - {% elseif tab == 'invoices' %} -
+ {% elseif tab == 'invoices' %} +

Mes factures

+ {% set paid_orders = orders|filter(o => o.status == 'paid') %} + {% if paid_orders|length > 0 %} +
+ {% for order in paid_orders %} +
+
+

Facture {{ order.orderNumber }}

+

{{ order.event.title }} — {{ order.paidAt ? order.paidAt|date('d/m/Y') : order.createdAt|date('d/m/Y') }}

+
+ {{ order.totalHTDecimal|number_format(2, ',', ' ') }} € + + Telecharger + +
+ {% endfor %} +
+ {% else %}

Aucune facture pour le moment.

+ {% endif %}
{% elseif tab == 'events' %} diff --git a/templates/order/public.html.twig b/templates/order/public.html.twig index 2e6ed28..0e532d4 100644 --- a/templates/order/public.html.twig +++ b/templates/order/public.html.twig @@ -47,6 +47,13 @@ {% endif %}

{% endif %} + {% if order.status == 'paid' %} + + {% endif %}
diff --git a/templates/order/success.html.twig b/templates/order/success.html.twig index 884829c..2a6b9d9 100644 --- a/templates/order/success.html.twig +++ b/templates/order/success.html.twig @@ -36,6 +36,9 @@

Vos billets ont ete envoyes a {{ order.email }}

+ + Telecharger la facture + Voir ma commande diff --git a/templates/pdf/invoice.html.twig b/templates/pdf/invoice.html.twig new file mode 100644 index 0000000..e3dc545 --- /dev/null +++ b/templates/pdf/invoice.html.twig @@ -0,0 +1,162 @@ + + + + + Facture {{ order.orderNumber }} + + + +
+ + + + + + +
+
Facture
+
{{ order.orderNumber }}
+
Date : {{ order.paidAt ? order.paidAt|date('d/m/Y') : order.createdAt|date('d/m/Y') }}
+
+ + + + + + + +
+
+
Vendeur / Organisateur
+
+ {{ organizer.companyName ?? (organizer.firstName ~ ' ' ~ organizer.lastName) }}
+ {% if organizer.siret %}SIRET : {{ organizer.siret }}
{% endif %} + {% if organizer.address %}{{ organizer.address }}
{% endif %} + {% if organizer.postalCode or organizer.city %}{{ organizer.postalCode }} {{ organizer.city }}
{% endif %} + {% if organizer.email %}{{ organizer.email }}
{% endif %} + {% if organizer.phone %}{{ organizer.phone }}{% endif %} +
+
+
+
+
Acheteur
+
+ {{ order.firstName }} {{ order.lastName }}
+ {{ order.email }} +
+
Evenement
+
+ {{ order.event.title }}
+ {{ order.event.startAt|date('d/m/Y') }} — {{ order.event.startAt|date('H:i') }} a {{ order.event.endAt|date('H:i') }}
+ {{ order.event.address }}, {{ order.event.zipcode }} {{ order.event.city }} +
+
+
+ + + + + + + + + + + + + {% for item in order.items %} + + + + + + + {% endfor %} + +
DescriptionQuantitePrix unitaire HTTotal HT
{{ item.billetName }}{{ item.quantity }}{{ item.unitPriceHTDecimal|number_format(2, ',', ' ') }} €{{ item.lineTotalHTDecimal|number_format(2, ',', ' ') }} €
+ + + + + + + + + + + + + + + +
Total HT{{ order.totalHTDecimal|number_format(2, ',', ' ') }} €
TVA (0%)0,00 €
Total TTC{{ order.totalHTDecimal|number_format(2, ',', ' ') }} €
+ + + {% if order.paymentMethod %} +
+
Paiement
+
+ {{ order.paymentMethod }} + {% if order.cardBrand and order.cardLast4 %} — {{ order.cardBrand|upper }} **** {{ order.cardLast4 }}{% endif %} + {% if order.paidAt %} — Paye le {{ order.paidAt|date('d/m/Y H:i') }}{% endif %} +
+
+ {% endif %} + + + +
+ +