diff --git a/src/Controller/Administrative/Disposition/DocumentUploadController.php b/src/Controller/Administrative/Disposition/DocumentUploadController.php new file mode 100644 index 0000000..e090c1a --- /dev/null +++ b/src/Controller/Administrative/Disposition/DocumentUploadController.php @@ -0,0 +1,117 @@ +workflow->can($disposition, 'upload_contract')) { + $uploadType = Upload::TYPE_CONTRACT; + $uploadTypeLabel = 'Honorarvertrag'; + $uploaderRoute = '_uploader_upload_contract'; + } elseif (true === $this->workflow->can($disposition, 'upload_invoice')) { + $uploadType = Upload::TYPE_INVOICE; + $uploadTypeLabel = 'Honoranote'; + $uploaderRoute = '_uploader_upload_invoice'; + } else { + $this->addFlash('error', 'Kein Upload möglich beim aktuellen Status der Einteilung'); + + return $this->getRedirectResponse($disposition); + } + + $teamer = $disposition->getTeamer(); + $modalTitle = sprintf('%s für %s hochladen', $uploadTypeLabel, $teamer); + + $form = $this->createFormBuilder()->getForm(); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->processUpload($disposition, $uploadType); + + $this->addFlash('success', sprintf('%s wurde hochgeladen', $uploadTypeLabel)); + + return $this->getRedirectResponse($disposition); + } + + return $this->render('administrative/disposition/modal_document_upload.html.twig', [ + 'disposition' => $disposition, + 'modalTitle' => $modalTitle, + 'uploaderRoute' => $uploaderRoute, + 'form' => $form->createView(), + ]); + } + + private function processUpload(Disposition $disposition, string $uploadType): void + { + if (null !== $existingUpload = $disposition->getDocumentByType($uploadType)) { + $this->entityManager->remove($existingUpload); + } + + $teamer = $disposition->getTeamer(); + $user = $teamer->getUser(); + + $uploadSession = $this->uploadHandler->getUploadSession(); + + $upload = Upload::fromUploadDto($uploadSession->getUploads()->first(), $user, $uploadType); + $upload->setStatus(Upload::STATUS_NEW); + + $disposition->addDocument($upload); + + $transitionName = sprintf('upload_%s', $uploadType); + $this->workflow->apply($disposition, $transitionName); + + $this->entityManager->flush(); + + $this->uploadHandler->moveUploadSessionFilesFromOrphanage($uploadType, $uploadSession); + $this->uploadHandler->destroyUploadSession(); + + $this->eventDispatcher->dispatch(new DocumentUploadedEvent($upload), DocumentUploadedEvent::NAME); + + $this->logger->info('Document upload for teamer', [ + 'teamer_id' => $teamer->getId(), + 'teamer_name' => $teamer->getFullName(), + 'disposition_id' => $disposition->getId(), + 'document_id' => $upload->getId(), + 'upload_type' => $uploadType, + ]); + } + + private function getRedirectResponse(Disposition $disposition): HxRedirectResponse + { + return new HxRedirectResponse($this->generateUrl('app_administrative_assignment_detail', [ + 'uuid' => $disposition->getAssignment()->getUuid(), + ])); + } +} diff --git a/src/EventListener/DispositionWorkflowGuardSubscriber.php b/src/EventListener/DispositionWorkflowGuardSubscriber.php index 65fe97d..fbc5859 100644 --- a/src/EventListener/DispositionWorkflowGuardSubscriber.php +++ b/src/EventListener/DispositionWorkflowGuardSubscriber.php @@ -4,13 +4,14 @@ namespace App\EventListener; use App\Entity\Disposition; use App\Entity\Upload; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Workflow\Event\GuardEvent; use Symfony\Contracts\Translation\TranslatorInterface; class DispositionWorkflowGuardSubscriber implements EventSubscriberInterface { - public function __construct(private readonly TranslatorInterface $translator) + public function __construct(private readonly TranslatorInterface $translator, private readonly Security $security) {} public static function getSubscribedEvents(): array @@ -40,6 +41,11 @@ class DispositionWorkflowGuardSubscriber implements EventSubscriberInterface public function guardUploadContract(GuardEvent $event): void { + // no checks for administrative users + if ($this->security->isGranted('ROLE_ADMINISTRATIVE')) { + return; + } + /** @var Disposition $disposition */ $disposition = $event->getSubject(); $assignment = $disposition->getAssignment(); @@ -79,6 +85,11 @@ class DispositionWorkflowGuardSubscriber implements EventSubscriberInterface $event->setBlocked(true, $message); } + // no further checks for administrative users + if ($this->security->isGranted('ROLE_ADMINISTRATIVE')) { + return; + } + $earliestDate = $destination->getDateTo(); if ($earliestDate > $today) { diff --git a/templates/administrative/assignment/detail.html.twig b/templates/administrative/assignment/detail.html.twig index b95deb4..aece30e 100644 --- a/templates/administrative/assignment/detail.html.twig +++ b/templates/administrative/assignment/detail.html.twig @@ -179,6 +179,15 @@