Skip to content

Commit

Permalink
Merge pull request #3114 from MTES-MCT/hotfix/3111-remove-attachement…
Browse files Browse the repository at this point in the history
…-mail-export

[BO - Export] Remplacer la pièce jointe de l'export par un lien téléchargeable en corps de mail
  • Loading branch information
emilschn authored Oct 3, 2024
2 parents a0e0400 + c67c86a commit 8cb7d67
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 49 deletions.
26 changes: 26 additions & 0 deletions migrations/Version20241001125833.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20241001125833 extends AbstractMigration
{
public function getDescription(): string
{
return 'Make signalement column nullable';
}

public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE file CHANGE signalement_id signalement_id INT DEFAULT NULL');
}

public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE file CHANGE signalement_id signalement_id INT NOT NULL');
}
}
10 changes: 10 additions & 0 deletions src/Controller/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Controller;

use App\Entity\Enum\DocumentType;
use App\Entity\File;
use App\Service\ImageManipulationHandler;
use League\Flysystem\FilesystemOperator;
Expand All @@ -10,6 +11,7 @@
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Attribute\Route;

class FileController extends AbstractController
Expand All @@ -24,6 +26,7 @@ public function showFile(
try {
$variant = $request->query->get('variant');
$filename = $file->getFilename();
$documentType = $file->getDocumentType();
$variantNames = ImageManipulationHandler::getVariantNames($filename);

if ('thumb' == $variant && $fileStorage->fileExists($variantNames[ImageManipulationHandler::SUFFIX_THUMB])) {
Expand All @@ -40,6 +43,13 @@ public function showFile(
file_put_contents($tmpFilepath, $content);
$file = new SymfonyFile($tmpFilepath);

if (DocumentType::EXPORT === $documentType) {
return (new BinaryFileResponse($file))->setContentDisposition(
ResponseHeaderBag::DISPOSITION_INLINE,
$file->getFilename()
);
}

return new BinaryFileResponse($file);
} catch (\Throwable $exception) {
$logger->error($exception->getMessage());
Expand Down
3 changes: 2 additions & 1 deletion src/Entity/Enum/DocumentType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum DocumentType: String
case AUTRE_PROCEDURE = 'AUTRE_PROCEDURE';
case PHOTO_SITUATION = 'PHOTO_SITUATION';
case PHOTO_VISITE = 'PHOTO_VISITE';
case EXPORT = 'EXPORT';

public static function getLabelList(): array
{
Expand Down Expand Up @@ -90,7 +91,7 @@ public function mapFileType(): ?string
self::PROCEDURE_SAISINE, self::BAILLEUR_DEVIS_POUR_TRAVAUX,
self::BAILLEUR_REPONSE_BAILLEUR, => File::FILE_TYPE_DOCUMENT,
self::PHOTO_SITUATION,self::PHOTO_VISITE => File::FILE_TYPE_PHOTO,
self::AUTRE, self::AUTRE_PROCEDURE => null,
self::AUTRE, self::AUTRE_PROCEDURE, self::EXPORT => null,
};
}
}
2 changes: 1 addition & 1 deletion src/Entity/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class File implements EntityHistoryInterface
private ?User $uploadedBy = null;

#[ORM\ManyToOne(inversedBy: 'files')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\JoinColumn(nullable: true)]
private ?Signalement $signalement = null;

#[ORM\Column(length: 255)]
Expand Down
52 changes: 38 additions & 14 deletions src/Messenger/MessageHandler/ListExportMessageHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,34 @@

namespace App\Messenger\MessageHandler;

use App\Entity\Enum\DocumentType;
use App\Manager\FileManager;
use App\Messenger\Message\ListExportMessage;
use App\Repository\UserRepository;
use App\Service\Mailer\NotificationMail;
use App\Service\Mailer\NotificationMailerRegistry;
use App\Service\Mailer\NotificationMailerType;
use App\Service\Signalement\Export\SignalementExportLoader;
use App\Service\TimezoneProvider;
use App\Service\UploadHandlerService;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Uid\Uuid;

#[AsMessageHandler]
class ListExportMessageHandler
readonly class ListExportMessageHandler
{
public function __construct(
private readonly NotificationMailerRegistry $notificationMailerRegistry,
private readonly LoggerInterface $logger,
private readonly SignalementExportLoader $signalementExportLoader,
private readonly UserRepository $userRepository,
private NotificationMailerRegistry $notificationMailerRegistry,
private LoggerInterface $logger,
private SignalementExportLoader $signalementExportLoader,
private UserRepository $userRepository,
private ParameterBagInterface $parameterBag,
private UploadHandlerService $uploadHandlerService,
private FileManager $fileManager
) {
}

Expand All @@ -44,18 +50,36 @@ public function __invoke(ListExportMessage $listExportMessage): void

if (isset($writer)) {
$timezone = $user->getTerritory()?->getTimezone() ?? TimezoneProvider::TIMEZONE_EUROPE_PARIS;
$datetimeStr = (new \DateTimeImmutable())->setTimezone(new \DateTimeZone($timezone))->format('Ymd-Hi');
$filename = 'export-histologe-'.$listExportMessage->getUserId().'-'.$datetimeStr.'.'.$format;
$datetimeStr = (new \DateTimeImmutable())->setTimezone(new \DateTimeZone($timezone))->format('Ymd-His');
$uuid = Uuid::v4();
$filename = 'export-histologe-'.$listExportMessage->getUserId().'-'.$datetimeStr.'-'.$uuid.'.'.$format;
$tmpFilepath = $this->parameterBag->get('uploads_tmp_dir').$filename;
$writer->save($tmpFilepath);

$this->notificationMailerRegistry->send(
new NotificationMail(
type: NotificationMailerType::TYPE_LIST_EXPORT,
to: $user->getEmail(),
attachment: $tmpFilepath
)
);
$filename = $this->uploadHandlerService->uploadFromFilename($filename);
if ($filename) {
$file = $this->fileManager->createOrUpdate(
filename: $filename,
title: $filename,
type: 'document',
user: $user,
flush: true,
documentType: DocumentType::EXPORT
);

$this->notificationMailerRegistry->send(
new NotificationMail(
type: NotificationMailerType::TYPE_LIST_EXPORT,
to: $user->getEmail(),
params: [
'filename' => $filename,
'file_uuid' => $file->getUuid(),
]
)
);
} else {
$this->logger->error('There was an issue generating your export');
}
}
} catch (\Throwable $exception) {
$this->logger->error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class SignalementListExportMailer extends AbstractNotificationMailer
{
protected ?NotificationMailerType $mailerType = NotificationMailerType::TYPE_LIST_EXPORT;
protected ?string $mailerSubject = 'Votre export de la liste des signalements';
protected ?string $mailerButtonText = 'Afficher l\'export';
protected ?string $mailerTemplate = 'signalement_list_export';

public function __construct(
Expand All @@ -27,10 +28,12 @@ public function __construct(

public function getMailerParamsFromNotification(NotificationMail $notificationMail): array
{
$attachment = $notificationMail->getAttachment();

return [
'attach' => $attachment,
'link' => $this->generateLink(
'show_file', [
'uuid' => $notificationMail->getParams()['file_uuid'],
]
),
];
}
}
21 changes: 18 additions & 3 deletions templates/emails/signalement_list_export.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@

{% block body %}
<p>Bonjour,</p>
<p>
Vous trouverez en pièce jointe de cet e-mail l'export de la liste des signalements.
</p>
<p>Un export de la liste des signalements est disponible.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary"
style="text-align: center">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr style="text-align: center;width: 100%">
<td>
<a href="{{ link|raw }}" target="_blank" rel="noopener">{{ btntext }}</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>
A bientôt sur Histologe !
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,65 @@
namespace App\Tests\Functional\Messenger\MessageHandler;

use App\Entity\User;
use App\Manager\FileManager;
use App\Messenger\Message\ListExportMessage;
use App\Messenger\MessageHandler\ListExportMessageHandler;
use App\Repository\UserRepository;
use App\Service\Mailer\NotificationMailerRegistry;
use App\Service\Signalement\Export\SignalementExportLoader;
use App\Service\UploadHandlerService;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\NotificationEmail;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Transport\TransportInterface;

class ListExportMessageHandlerTest extends WebTestCase
{
public function testHandleGenerateListCsv()
private MessageBusInterface $messageBus;
private UserRepository $userRepository;
private TransportInterface $transport;

protected function setUp(): void
{
self::bootKernel();
$this->userRepository = static::getContainer()->get(UserRepository::class);
$this->transport = static::getContainer()->get('messenger.transport.async_priority_high');
$this->messageBus = static::getContainer()->get(MessageBusInterface::class);
}

$container = static::getContainer();

$messageBus = $container->get(MessageBusInterface::class);

public function testHandleGenerateListCsv()
{
$userEmail = 'admin-01@histologe.fr';

$userRepository = static::getContainer()->get(UserRepository::class);
/** @var User $user */
$user = $userRepository->findOneBy(['email' => $userEmail]);
$user = $this->userRepository->findOneBy(['email' => $userEmail]);
$message = (new ListExportMessage())
->setUserId($user->getId())
->setFormat('csv')
->setFilters([])
->setSelectedColumns([]);

$messageBus->dispatch($message);

$transport = $container->get('messenger.transport.async_priority_high');
$envelopes = $transport->get();
$this->messageBus->dispatch($message);
$envelopes = $this->transport->get();
$this->assertCount(1, $envelopes);

$handler = $container->get(ListExportMessageHandler::class);
$uploadHandlerServiceMock = $this->createMock(UploadHandlerService::class);
$uploadHandlerServiceMock
->expects($this->once())
->method('uploadFromFilename')
->willReturn('sample.csv');

$handler = new ListExportMessageHandler(
static::getContainer()->get(NotificationMailerRegistry::class),
static::getContainer()->get(LoggerInterface::class),
static::getContainer()->get(SignalementExportLoader::class),
static::getContainer()->get(UserRepository::class),
static::getContainer()->get(ParameterBagInterface::class),
$uploadHandlerServiceMock,
static::getContainer()->get(FileManager::class)
);

$handler($message);
$this->assertEmailCount(1);
/** @var NotificationEmail $email */
Expand All @@ -48,30 +72,35 @@ public function testHandleGenerateListCsv()

public function testHandleGenerateListXlsWithOptions()
{
self::bootKernel();

$container = static::getContainer();

$messageBus = $container->get(MessageBusInterface::class);

$userEmail = 'admin-territoire-13-01@histologe.fr';

$userRepository = static::getContainer()->get(UserRepository::class);
/** @var User $user */
$user = $userRepository->findOneBy(['email' => $userEmail]);
$user = $this->userRepository->findOneBy(['email' => $userEmail]);
$message = (new ListExportMessage())
->setUserId($user->getId())
->setFormat('xlsx')
->setFilters([])
->setSelectedColumns(['INSEE']);

$messageBus->dispatch($message);

$transport = $container->get('messenger.transport.async_priority_high');
$envelopes = $transport->get();
$this->messageBus->dispatch($message);
$envelopes = $this->transport->get();
$this->assertCount(1, $envelopes);

$handler = $container->get(ListExportMessageHandler::class);
$uploadHandlerServiceMock = $this->createMock(UploadHandlerService::class);
$uploadHandlerServiceMock
->expects($this->once())
->method('uploadFromFilename')
->willReturn('sample.xlsx');

$handler = new ListExportMessageHandler(
static::getContainer()->get(NotificationMailerRegistry::class),
static::getContainer()->get(LoggerInterface::class),
static::getContainer()->get(SignalementExportLoader::class),
static::getContainer()->get(UserRepository::class),
static::getContainer()->get(ParameterBagInterface::class),
$uploadHandlerServiceMock,
static::getContainer()->get(FileManager::class)
);

$handler($message);
$this->assertEmailCount(1);
/** @var NotificationEmail $email */
Expand Down

0 comments on commit 8cb7d67

Please sign in to comment.