Feat: Implement invoice pdf download for teamer

This commit is contained in:
Björn Fromme
2023-10-13 14:48:55 +02:00
parent 0685cd4c96
commit 98fc5fbf8b
5 changed files with 52 additions and 5 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

+4
View File
@@ -109,3 +109,7 @@ services:
App\Service\Pdf\ContractRenderer: App\Service\Pdf\ContractRenderer:
arguments: arguments:
$options: { 'project_dir': '%kernel.project_dir%' } $options: { 'project_dir': '%kernel.project_dir%' }
App\Service\Pdf\InvoiceRenderer:
arguments:
$options: { 'project_dir': '%kernel.project_dir%' }
@@ -0,0 +1,36 @@
<?php
namespace App\Controller\Teamer\Disposition;
use App\Entity\Disposition;
use App\Service\Pdf\InvoiceRenderer;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class InvoicePdfController extends AbstractController
{
public function __construct(private readonly InvoiceRenderer $renderer)
{}
#[Route('/teamer/disposition/invoice/{uuid}', name: 'app_teamer_disposition_invoicepdf')]
#[IsGranted('INVOICE', subject: 'disposition')]
public function index(Disposition $disposition): Response
{
$pdf = $this->renderer->render($disposition);
$teamer = $disposition->getTeamer();
$filename = sprintf('Honorarnote_%s_%s.pdf', $teamer, $disposition->getAssignment()->getDestination());
$disposition = HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $filename, md5($filename));
$response = new Response($pdf->Output('S'));
$response->setPrivate();
$response->headers->set('Content-type', 'application/pdf');
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
}
+9 -2
View File
@@ -13,6 +13,7 @@ class DispositionVoter extends Voter
public const EDIT = 'EDIT'; public const EDIT = 'EDIT';
public const DELETE = 'DELETE'; public const DELETE = 'DELETE';
public const CONTRACT = 'CONTRACT'; public const CONTRACT = 'CONTRACT';
public const INVOICE = 'INVOICE';
protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
@@ -20,7 +21,7 @@ class DispositionVoter extends Voter
return false; return false;
} }
return in_array($attribute, [static::VIEW, static::EDIT, static::DELETE, static::CONTRACT]); return in_array($attribute, [static::VIEW, static::EDIT, static::DELETE, static::CONTRACT, static::INVOICE]);
} }
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
@@ -31,15 +32,21 @@ class DispositionVoter extends Voter
} }
// Teamers may only view or edit their own dispositions // Teamers may only view or edit their own dispositions
if (in_array('ROLE_TEAMER', $token->getRoleNames()) && in_array($attribute, [static::VIEW, static::EDIT, static::CONTRACT])) { if (in_array('ROLE_TEAMER', $token->getRoleNames())) {
/** @var User $user */ /** @var User $user */
$user = $token->getUser(); $user = $token->getUser();
$teamer = $user->getTeamer(); $teamer = $user->getTeamer();
/** @var Disposition $disposition */ /** @var Disposition $disposition */
$disposition = $subject; $disposition = $subject;
switch ($attribute) {
case static::VIEW:
case static::EDIT:
case static::CONTRACT:
case static::INVOICE:
return $teamer === $disposition->getTeamer(); return $teamer === $disposition->getTeamer();
} }
}
return false; return false;
} }
@@ -68,8 +68,8 @@
Hier findest du deine Honorarnote Hier findest du deine Honorarnote
</h3> </h3>
<div class="pb-4"> <div class="pb-4">
<a href="{{ path('app_teamer_disposition_contractpdf', { 'uuid': disposition.uuid }) }}" target="_blank" class="inline-block"> <a href="{{ path('app_teamer_disposition_invoicepdf', { 'uuid': disposition.uuid }) }}" target="_blank" class="inline-block">
<img src="{{ asset('build/images/contract_thumb.jpg') }}" alt="Honorarvertrag" class="block w-32 h-auto shadow-md"> <img src="{{ asset('build/images/invoice_thumb.jpg') }}" alt="Honorarnote" class="block w-32 h-auto shadow-md">
</a> </a>
</div> </div>
<p class="pb-4"> <p class="pb-4">