From 24c8c46ca47ad043824eadf3fd1795c93a2ce3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Sat, 1 Feb 2025 11:42:21 +0100 Subject: [PATCH] feat: dedicated list view for document batch downloading --- .../Document/BatchDownloadController.php | 7 +- .../Document/IndexController.php | 30 +++++ src/Controller/Common/DownloadController.php | 14 ++- src/Menu/AdminMenuBuilder.php | 21 +++- src/Repository/UploadRepository.php | 24 +++- .../document/accepted.html.twig | 113 ++++++++++++++++++ .../administrative/document/index.html.twig | 4 - 7 files changed, 195 insertions(+), 18 deletions(-) create mode 100644 templates/administrative/document/accepted.html.twig diff --git a/src/Controller/Administrative/Document/BatchDownloadController.php b/src/Controller/Administrative/Document/BatchDownloadController.php index ba190b7..f006463 100644 --- a/src/Controller/Administrative/Document/BatchDownloadController.php +++ b/src/Controller/Administrative/Document/BatchDownloadController.php @@ -8,7 +8,6 @@ use App\Service\Upload\UploadHandler; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\HeaderUtils; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\Routing\Attribute\Route; @@ -32,9 +31,9 @@ class BatchDownloadController extends AbstractController defaults: ['type' => Upload::TYPE_INVOICE] )] #[IsGranted('ROLE_ADMINISTRATIVE')] - public function index(string $type, Request $request): Response + public function index(string $type): Response { - $status = $request->query->get('status', Upload::STATUS_PAID); + $status = Upload::TYPE_INVOICE === $type ? Upload::STATUS_PAID : Upload::STATUS_CHECKED; $uploads = $this ->uploadRepository @@ -47,7 +46,7 @@ class BatchDownloadController extends AbstractController return $this->redirectToRoute('app_administrative_document_index'); } - $zipFilename = sprintf('Honorarnoten_%s.zip', date('YmdHi')); + $zipFilename = sprintf('%ss_%s.zip', $type, date('YmdHi')); $response = new StreamedResponse(function () use ($uploads, $zipFilename) { $zip = new ZipStream( diff --git a/src/Controller/Administrative/Document/IndexController.php b/src/Controller/Administrative/Document/IndexController.php index e71a83e..86890b4 100644 --- a/src/Controller/Administrative/Document/IndexController.php +++ b/src/Controller/Administrative/Document/IndexController.php @@ -2,6 +2,8 @@ namespace App\Controller\Administrative\Document; +use App\Entity\Upload; +use App\Model\DocumentFilterDto; use App\Repository\UploadRepository; use App\Service\Common\DocumentFilterHandler; use Knp\Component\Pager\PaginatorInterface; @@ -42,4 +44,32 @@ class IndexController extends AbstractController 'filterDto' => $filterDto, ]); } + + #[Route( + path: '/administrative/document/accepted/{type}', + name: 'app_administrative_document_accepted', + defaults: ['type' => Upload::TYPE_INVOICE] + )] + #[IsGranted('ROLE_ADMINISTRATIVE')] + public function accepted(string $type, Request $request): Response + { + $status = Upload::TYPE_INVOICE === $type ? Upload::STATUS_PAID : Upload::STATUS_CHECKED; + + $query = $this + ->uploadRepository + ->getBatchDownloadListQuery($type, $status) + ; + + $pagination = $this->paginator->paginate( + $query, + $request->query->getInt('page', 1), + $request->query->getInt('limit', 50), + ); + + return $this->render('administrative/document/accepted.html.twig', [ + 'pagination' => $pagination, + 'type' => $type, + 'status' => $status, + ]); + } } \ No newline at end of file diff --git a/src/Controller/Common/DownloadController.php b/src/Controller/Common/DownloadController.php index d682372..0cbbc13 100644 --- a/src/Controller/Common/DownloadController.php +++ b/src/Controller/Common/DownloadController.php @@ -33,12 +33,14 @@ class DownloadController extends AbstractController $inline = (bool) $request->get('inline'); $disposition = $inline ? ResponseHeaderBag::DISPOSITION_INLINE : ResponseHeaderBag::DISPOSITION_ATTACHMENT; - // mark file downloaded - $upload - ->setDownloaded() - ->setDownloadedBy($this->getUser()->getUserIdentifier()) - ; - $this->entityManager->flush(); + // mark file downloaded if applicable + if ($this->isGranted('ROLE_ADMINISTRATIVE' && false === $inline)) { + $upload + ->setDownloaded() + ->setDownloadedBy($this->getUser()->getUserIdentifier()) + ; + $this->entityManager->flush(); + } $this->logger->info('Download file', [ 'file_id' => $upload->getId(), diff --git a/src/Menu/AdminMenuBuilder.php b/src/Menu/AdminMenuBuilder.php index 9e9d926..6db50c8 100644 --- a/src/Menu/AdminMenuBuilder.php +++ b/src/Menu/AdminMenuBuilder.php @@ -2,6 +2,7 @@ namespace App\Menu; +use App\Entity\Upload; use Knp\Menu\ItemInterface; class AdminMenuBuilder extends AbstractMenuBuilder @@ -40,7 +41,7 @@ class AdminMenuBuilder extends AbstractMenuBuilder 'icon' => 'mail', ], ]); - $menu->addChild('Dokumentenübersicht', [ + $documentMenu = $menu->addChild('Dokumentenübersicht', [ 'route' => 'app_administrative_document_index', 'linkAttributes' => [ 'title' => 'Dokumentenübersicht', @@ -49,6 +50,24 @@ class AdminMenuBuilder extends AbstractMenuBuilder 'icon' => 'document', ], ]); + $documentMenu->addChild('akzeptierte Honorarnoten', [ + 'route' => 'app_administrative_document_accepted', + 'routeParameters' => [ + 'type' => Upload::TYPE_INVOICE, + ], + 'linkAttributes' => [ + 'title' => 'akzeptierte Honorarnoten', + ], + ]); + $documentMenu->addChild('geprüfte Honorverträge', [ + 'route' => 'app_administrative_document_accepted', + 'routeParameters' => [ + 'type' => Upload::TYPE_CONTRACT, + ], + 'linkAttributes' => [ + 'title' => 'geprüfte Honorverträge', + ], + ]); $menu->addChild('Feedbackübersicht', [ 'route' => 'app_administrative_feedback_index', 'linkAttributes' => [ diff --git a/src/Repository/UploadRepository.php b/src/Repository/UploadRepository.php index 10eace9..5f7532d 100644 --- a/src/Repository/UploadRepository.php +++ b/src/Repository/UploadRepository.php @@ -80,12 +80,21 @@ class UploadRepository extends ServiceEntityRepository return $data; } - public function getBatchDownloadList( + public function getBatchDownloadListQuery( string $type = Upload::TYPE_INVOICE, string $status = Upload::STATUS_PAID - ): array { + ): Query { $qb = $this->createQueryBuilder('upload'); + $qb + ->select('upload', 'disposition', 'assignment', 'job_profile', 'destination', 'teamer') + ->innerJoin('upload.disposition', 'disposition') + ->innerJoin('disposition.assignment', 'assignment') + ->innerJoin('assignment.jobProfile', 'job_profile') + ->innerJoin('assignment.destination', 'destination') + ->innerJoin('disposition.teamer', 'teamer') + ; + return $qb->where( $qb->expr()->andX( $qb->expr()->eq('upload.type', ':type'), @@ -95,10 +104,19 @@ class UploadRepository extends ServiceEntityRepository ->setParameter('type', $type) ->setParameter('status', $status) ->getQuery() - ->getResult() ; } + public function getBatchDownloadList( + string $type = Upload::TYPE_INVOICE, + string $status = Upload::STATUS_PAID + ): array { + return $this + ->getBatchDownloadListQuery($type, $status) + ->getResult() + ; + } + public function getUploadListQuery(DocumentFilterDto $filterDto): Query { $qb = $this->createQueryBuilder('upload'); diff --git a/templates/administrative/document/accepted.html.twig b/templates/administrative/document/accepted.html.twig new file mode 100644 index 0000000..bdbddf0 --- /dev/null +++ b/templates/administrative/document/accepted.html.twig @@ -0,0 +1,113 @@ +{% extends 'administrative/layout.html.twig' %} + +{% block title %}Dokumentenübersicht{% endblock %} + +{% block content %} +
+

+ {% if type == constant('App\\Entity\\Upload::TYPE_INVOICE') %} + Übersicht akzeptierte Honorarnoten + {% elseif type == constant('App\\Entity\\Upload::TYPE_CONTRACT') %} + Übersicht geprüfte Honorarverträge + {% else %} + Übersicht + {% endif %} +

+ +
+
+
+ + + + + + + + + + + + + + {% for upload in pagination %} + {% set disposition = upload.disposition %} + {% set assignment = disposition.assignment %} + + + + + + + + + + {% else %} + + + + {% endfor %} + +
+ {{ knp_pagination_sortable(pagination, 'Einsatz­zeitraum', 'destination.dateFrom') }} + + {{ knp_pagination_sortable(pagination, 'Destination', 'destination.product') }} + + {{ knp_pagination_sortable(pagination, 'Jobprofil', 'job_profile.name') }} + + {{ knp_pagination_sortable(pagination, 'Dokument', 'upload.type') }} + + {{ knp_pagination_sortable(pagination, 'Teamer:in', 'teamer.lastName') }} + + {{ knp_pagination_sortable(pagination, 'Status', 'upload.status') }} +
+ {{ assignment.destination.dateFrom|date('d.m.Y') }} + - + {{ assignment.destination.dateTo|date('d.m.Y') }} + +
+ {{ icon('flag-' ~ assignment.destination.country, 'w-5 h-5 shrink-0') }} +
+ {{ assignment.destination.product }} +
+ {{ assignment.destination.hotel }} +
+
+
+ {{ assignment.jobProfile.name }} + + {{ ('label.document.type.' ~ upload.type)|trans }} + + {{ disposition.teamer }} + + {{ upload.status|upload_status_badge }} + +
+ {% if is_granted('DELETE', upload) %} + + {% endif %} + + {{ icon('download') }} + +
+
+ Keine Daten... +
+ {{ knp_pagination_render(pagination) }} +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/administrative/document/index.html.twig b/templates/administrative/document/index.html.twig index daf69ba..b0e05f2 100644 --- a/templates/administrative/document/index.html.twig +++ b/templates/administrative/document/index.html.twig @@ -8,10 +8,6 @@ Dokumentenübersicht
- - {{ icon('download', 'w-4 h-4 shrink-0') }} - best. Honorarnoten -