Repository: MTES-MCT/histologe
Pull request #3928: [BO - Export signalements] Ajouter la colonne commentaire de clôture
Author: login: numew
Created: 2025-04-01T15:00:23Z | Merged: 2025-04-08T14:19:41Z

## Ticket

#3880

## Description
Possibilité de rajouter le "Commentaire de cloture" dans l'export des signalements

## Changements apportés
* Ajout d'une colonne "com_cloture" sur la table signalement
* Enregistrement de cette colonne pour les signalements existant en base (à partir du suivi correspondant)
* Enregistrement de cette colonne à la cloture pour tous d'un signalement
* Ajout de la colonne sur l'export

## Pré-requis
make execute-migration name=Version20250401111532 direction=up

## Tests
- [ ] Clôturer un signalement pour tous et l'exporter en cochant la colonne "Commentaire de cloture"



Diff:
diff --git a/migrations/Version20250401111532.php b/migrations/Version20250401111532.php
new file mode 100644
index 0000000000..a549eafc1e
--- /dev/null
+++ b/migrations/Version20250401111532.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('<strong>Desc. : </strong>', $item['description']);
+            $comCloture = $exploded[count($exploded) - 1];
+            $this->addSql('UPDATE signalement SET com_cloture = ? WHERE id = ?', [$comCloture, $item['signalement_id']]);
+        }
+    }
+
+    private function getSuiviCloturePourTous(): array
+    {
+        $query = 'SELECT signalement_id, description FROM suivi WHERE description LIKE "Le signalement a été cloturé pour tous les partenaires avec le motif suivant%"';
+
+        return $this->connection->fetchAllAssociative($query);
+    }
+
+    public function down(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement DROP com_cloture');
+    }
+}
diff --git a/src/Controller/Back/SignalementController.php b/src/Controller/Back/SignalementController.php
index 8c05dba21c..76ace363b3 100755
--- a/src/Controller/Back/SignalementController.php
+++ b/src/Controller/Back/SignalementController.php
@@ -135,7 +135,8 @@ public function viewSignalement(
                 $eventParams['subject'] = 'tous les partenaires';
                 $entity = $signalement = $signalementManager->closeSignalementForAllPartners(
                     $signalement,
-                    $eventParams['motif_cloture']
+                    $eventParams['motif_cloture'],
+                    $eventParams['motif_suivi']
                 );
                 $reference = $signalement->getReference();
                 $eventDispatcher->dispatch(new SignalementClosedEvent($entity, $eventParams), SignalementClosedEvent::NAME);
diff --git a/src/Dto/SignalementExport.php b/src/Dto/SignalementExport.php
index 33167ebd56..2b30677de8 100644
--- a/src/Dto/SignalementExport.php
+++ b/src/Dto/SignalementExport.php
@@ -60,6 +60,7 @@ public function __construct(
         public ?string $modifiedAt = null,
         public ?string $closedAt = null,
         public ?string $motifCloture = null,
+        public ?string $comCloture = null,
         public ?string $longitude = null,
         public ?string $latitude = null,
     ) {
diff --git a/src/Entity/Signalement.php b/src/Entity/Signalement.php
index 7ce78f61ae..850f80cfac 100644
--- a/src/Entity/Signalement.php
+++ b/src/Entity/Signalement.php
@@ -23,6 +23,7 @@
 use App\Validator as AppAssert;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
+use Doctrine\DBAL\Types\Types;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Uid\Uuid;
 use Symfony\Component\Validator\Constraints as Assert;
@@ -444,6 +445,9 @@ class Signalement implements EntityHistoryInterface, EntityHistoryCollectionInte
     #[ORM\Column(type: 'boolean', nullable: true)]
     private ?bool $hasSeenDesordres = null;
 
+    #[ORM\Column(type: Types::TEXT, nullable: true)]
+    private ?string $comCloture = null;
+
     public function __construct()
     {
         $this->situations = new ArrayCollection();
@@ -2546,4 +2550,16 @@ public function setHasSeenDesordres(?bool $hasSeenDesordres): static
 
         return $this;
     }
+
+    public function getComCloture(): ?string
+    {
+        return $this->comCloture;
+    }
+
+    public function setComCloture(?string $comCloture): static
+    {
+        $this->comCloture = $comCloture;
+
+        return $this;
+    }
 }
diff --git a/src/Factory/SignalementExportFactory.php b/src/Factory/SignalementExportFactory.php
index 110bdee810..fb41030ca6 100644
--- a/src/Factory/SignalementExportFactory.php
+++ b/src/Factory/SignalementExportFactory.php
@@ -129,6 +129,7 @@ public function createInstanceFrom(User $user, array $data): SignalementExport
             modifiedAt: $modifiedAt,
             closedAt: $closedAt,
             motifCloture: $motifCloture,
+            comCloture: $data['comCloture'],
             longitude: is_array($geoloc) ? $geoloc['lng'] ?? '' : '',
             latitude: is_array($geoloc) ? $geoloc['lat'] ?? '' : '',
         );
diff --git a/src/Manager/SignalementManager.php b/src/Manager/SignalementManager.php
index 3bcbba0ccc..0ea81f0f2a 100644
--- a/src/Manager/SignalementManager.php
+++ b/src/Manager/SignalementManager.php
@@ -49,7 +49,9 @@
 use Doctrine\DBAL\Exception;
 use Doctrine\Persistence\ManagerRegistry;
 use Symfony\Bundle\SecurityBundle\Security;
+use Symfony\Component\DependencyInjection\Attribute\Autowire;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
 
 class SignalementManager extends AbstractManager
 {
@@ -71,6 +73,8 @@ public function __construct(
         private readonly AffectationRepository $affectationRepository,
         private readonly SignalementAddressUpdater $signalementAddressUpdater,
         private readonly ZipcodeProvider $zipcodeProvider,
+        #[Autowire(service: 'html_sanitizer.sanitizer.app.message_sanitizer')]
+        private readonly HtmlSanitizerInterface $htmlSanitizer,
         string $entityName = Signalement::class,
     ) {
         parent::__construct($managerRegistry, $entityName);
@@ -220,12 +224,13 @@ function (Affectation $affectation) {
         return $affectation->toArray();
     }
 
-    public function closeSignalementForAllPartners(Signalement $signalement, MotifCloture $motif): Signalement
+    public function closeSignalementForAllPartners(Signalement $signalement, MotifCloture $motif, string $comCloture): Signalement
     {
         $signalement
             ->setStatut(SignalementStatus::CLOSED)
             ->setMotifCloture($motif)
-            ->setClosedAt(new \DateTimeImmutable());
+            ->setClosedAt(new \DateTimeImmutable())
+            ->setComCloture($this->htmlSanitizer->sanitize($comCloture));
 
         /** @var User $user */
         $user = $this->security->getUser();
diff --git a/src/Repository/SignalementRepository.php b/src/Repository/SignalementRepository.php
index a405b22923..14cefc0b85 100755
--- a/src/Repository/SignalementRepository.php
+++ b/src/Repository/SignalementRepository.php
@@ -595,6 +595,7 @@ public function findSignalementAffectationIterable(User $user, array $options):
             s.modifiedAt,
             s.closedAt,
             s.motifCloture,
+            s.comCloture,
             s.geoloc,
             s.typeCompositionLogement,
             s.informationProcedure,
diff --git a/src/Service/Signalement/Export/SignalementExportHeader.php b/src/Service/Signalement/Export/SignalementExportHeader.php
index 596e7c2aa7..e051641187 100644
--- a/src/Service/Signalement/Export/SignalementExportHeader.php
+++ b/src/Service/Signalement/Export/SignalementExportHeader.php
@@ -62,6 +62,7 @@ public static function getHeaders(): array
             'Dernière MAJ le',
             'Clôturé le',
             'Motif de clôture',
+            'Commentaire de clôture',
             'Longitude',
             'Latitude',
         ];
diff --git a/src/Service/Signalement/Export/SignalementExportSelectableColumns.php b/src/Service/Signalement/Export/SignalementExportSelectableColumns.php
index 5960bef43e..01accd2f44 100644
--- a/src/Service/Signalement/Export/SignalementExportSelectableColumns.php
+++ b/src/Service/Signalement/Export/SignalementExportSelectableColumns.php
@@ -41,6 +41,7 @@ class SignalementExportSelectableColumns
         'DERNIERE_MAJ' => ['name' => 'Dernière MAJ le', 'description' => 'La date de la dernière mise à jour du signalement', 'export' => 'modifiedAt'],
         'DATE_CLOTURE' => ['name' => 'Fermé le', 'description' => 'La date de clôture du signalement', 'export' => 'closedAt'],
         'MOTIF_CLOTURE' => ['name' => 'Motif de clôture', 'description' => 'Le motif de clôture du signalement', 'export' => 'motifCloture'],
+        'COM_CLOTURE' => ['name' => 'Commentaire de clôture', 'description' => 'Le commentaire de clôture du signalement', 'export' => 'comCloture'],
         'GEOLOCALISATION' => ['name' => 'Géolocalisation', 'description' => 'Les coordonnées GPS du logement', 'export' => 'geoloc'],
         'DEBUT_DESORDRES' => ['name' => 'Début des désordres', 'description' => 'Début des désordres', 'export' => 'debutDesordres'],
     ];
diff --git a/tests/Functional/Manager/SignalementManagerTest.php b/tests/Functional/Manager/SignalementManagerTest.php
index 779934db55..fc1b0337c3 100644
--- a/tests/Functional/Manager/SignalementManagerTest.php
+++ b/tests/Functional/Manager/SignalementManagerTest.php
@@ -32,6 +32,7 @@
 use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
 use Symfony\Bundle\SecurityBundle\Security;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
 use Symfony\Component\Validator\ConstraintViolationList;
 use Symfony\Component\Validator\Validator\ValidatorInterface;
 
@@ -58,6 +59,7 @@ class SignalementManagerTest extends WebTestCase
     private SignalementAddressUpdater $signalementAddressUpdater;
     private AffectationRepository $affectationRepository;
     private ZipcodeProvider $zipcodeProvider;
+    private HtmlSanitizerInterface $htmlSanitizerInterface;
 
     protected function setUp(): void
     {
@@ -83,6 +85,7 @@ protected function setUp(): void
         $this->signalementAddressUpdater = static::getContainer()->get(SignalementAddressUpdater::class);
         $this->affectationRepository = static::getContainer()->get(AffectationRepository::class);
         $this->zipcodeProvider = static::getContainer()->get(ZipcodeProvider::class);
+        $this->htmlSanitizerInterface = self::getContainer()->get('html_sanitizer.sanitizer.app.message_sanitizer');
 
         $this->signalementManager = new SignalementManager(
             $this->managerRegistry,
@@ -101,7 +104,8 @@ protected function setUp(): void
             $this->bailleurRepository,
             $this->affectationRepository,
             $this->signalementAddressUpdater,
-            $this->zipcodeProvider
+            $this->zipcodeProvider,
+            $this->htmlSanitizerInterface,
         );
         $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => 'admin-01@signal-logement.fr']);
         $client->loginUser($user);
@@ -126,9 +130,13 @@ public function testCloseSignalementForAllPartners()
 
         $signalementClosed = $this->signalementManager->closeSignalementForAllPartners(
             $signalementActive,
-            MotifCloture::tryFrom('TRAVAUX_FAITS_OU_EN_COURS')
+            MotifCloture::tryFrom('TRAVAUX_FAITS_OU_EN_COURS'),
+            'Tous les problèmes ont été résolus en moins de 15 ans',
         );
 
+        $this->assertEquals($signalementActive->getComCloture(), 'Tous les problèmes ont été résolus en moins de 15 ans');
+        $this->assertEquals($signalementClosed->getComCloture(), 'Tous les problèmes ont été résolus en moins de 15 ans');
+
         $this->assertInstanceOf(Signalement::class, $signalementClosed);
         $this->assertEquals(SignalementStatus::CLOSED, $signalementClosed->getStatut());
         $this->assertEquals('Travaux faits ou en cours', $signalementClosed->getMotifCloture()->label());
diff --git a/tests/Functional/Service/Signalement/PhotoHelperTest.php b/tests/Functional/Service/Signalement/PhotoHelperTest.php
index 240a29b6ac..27d9163c4a 100644
--- a/tests/Functional/Service/Signalement/PhotoHelperTest.php
+++ b/tests/Functional/Service/Signalement/PhotoHelperTest.php
@@ -23,6 +23,7 @@
 use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
 use Symfony\Bundle\SecurityBundle\Security;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
 
 class PhotoHelperTest extends KernelTestCase
 {
@@ -44,6 +45,7 @@ class PhotoHelperTest extends KernelTestCase
     private SignalementAddressUpdater $signalementAddressUpdater;
     private AffectationRepository $affectationRepository;
     private ZipcodeProvider $zipcodeProvider;
+    private HtmlSanitizerInterface $htmlSanitizerInterface;
 
     protected function setUp(): void
     {
@@ -67,6 +69,7 @@ protected function setUp(): void
         $this->signalementAddressUpdater = static::getContainer()->get(SignalementAddressUpdater::class);
         $this->affectationRepository = static::getContainer()->get(AffectationRepository::class);
         $this->zipcodeProvider = static::getContainer()->get(ZipcodeProvider::class);
+        $this->htmlSanitizerInterface = self::getContainer()->get('html_sanitizer.sanitizer.app.message_sanitizer');
 
         $this->signalementManager = new SignalementManager(
             $this->managerRegistry,
@@ -85,7 +88,8 @@ protected function setUp(): void
             $this->bailleurRepository,
             $this->affectationRepository,
             $this->signalementAddressUpdater,
-            $this->zipcodeProvider
+            $this->zipcodeProvider,
+            $this->htmlSanitizerInterface
         );
     }
 
diff --git a/tests/Unit/Factory/SignalementExportFactoryTest.php b/tests/Unit/Factory/SignalementExportFactoryTest.php
index 2173863903..98814ff724 100644
--- a/tests/Unit/Factory/SignalementExportFactoryTest.php
+++ b/tests/Unit/Factory/SignalementExportFactoryTest.php
@@ -67,6 +67,7 @@ public function testCreateSignalementExportFactory(): void
             'modifiedAt' => new \DateTimeImmutable(),
             'closedAt' => new \DateTimeImmutable(),
             'motifCloture' => MotifCloture::INSALUBRITE,
+            'comCloture' => null,
             'familleSituation' => "l'état et propreté du logement|l'état et propreté du logement|",
             'desordres' => "Les sols sont humides.|Les installations électriques ne sont pas en bon état.|
                 Les murs ont des fissures.|De l'eau s’infiltre dans mon logement.|Il y a des trace ",


Reviews:
user: login: emilschn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T07:59:14Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T08:01:52Z
user: login: hmeneuvrier
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T12:23:48Z
user: login: hmeneuvrier
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T12:27:57Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T13:35:36Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T13:36:00Z
user: login: hmeneuvrier
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-07T08:02:52Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-08T08:33:32Z
user: login: hmeneuvrier
body: OK pour moi
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-08T10:26:18Z
user: login: emilschn
body: OK lecture et tests
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-08T14:19:30Z

Review comments:
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
path: migrations/Version20250401111532.php
user: login: emilschn
body: t'es sûr de ça ? si quelqu'un met du gras dans son texte quand il commente, ça va faire un truc partiel, non ?
created_at: 2025-04-03T07:59:14Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
path: migrations/Version20250401111532.php
user: login: numew
body: ha oui j'avais pas pensé à ca je regarderais, bien vu merci
created_at: 2025-04-03T08:01:52Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
+            $comCloture = $exploded[count($exploded) - 1];
+            $this->addSql('UPDATE signalement SET com_cloture = ? WHERE id = ?', [$comCloture, $item['signalement_id']]);
+        }
+    }
+
+    private function getSuiviCloturePourTous(): array
+    {
+        $query = 'SELECT signalement_id, description FROM suivi WHERE description LIKE "Le signalement a été cloturé pour tous les partenaires avec le motif suivant%"';
path: migrations/Version20250401111532.php
user: login: hmeneuvrier
body: Vérifier dans Metabase (ou dans le code), il me semble qu'il y a eu 2 écritures différentes
created_at: 2025-04-03T12:23:48Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
+            $comCloture = $exploded[count($exploded) - 1];
+            $this->addSql('UPDATE signalement SET com_cloture = ? WHERE id = ?', [$comCloture, $item['signalement_id']]);
+        }
+    }
+
+    private function getSuiviCloturePourTous(): array
+    {
+        $query = 'SELECT signalement_id, description FROM suivi WHERE description LIKE "Le signalement a été cloturé pour tous les partenaires avec le motif suivant%"';
path: migrations/Version20250401111532.php
user: login: hmeneuvrier
body: ![image](https://github.com/user-attachments/assets/f702bd41-8f36-4422-bd51-2b1a7478bdf4)


created_at: 2025-04-03T12:27:57Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
path: migrations/Version20250401111532.php
user: login: numew
body: bon ca à pas l'air de changer grand chose d’après mes tests sur base de prod mais c'est fait.
created_at: 2025-04-03T13:35:35Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250401111532 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add com_cloture column to signalement table and populate it with data from suivi table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE signalement ADD com_cloture LONGTEXT DEFAULT NULL');
+        $list = $this->getSuiviCloturePourTous();
+        foreach ($list as $item) {
+            $exploded = explode('</strong>', $item['description']);
+            $comCloture = $exploded[count($exploded) - 1];
+            $this->addSql('UPDATE signalement SET com_cloture = ? WHERE id = ?', [$comCloture, $item['signalement_id']]);
+        }
+    }
+
+    private function getSuiviCloturePourTous(): array
+    {
+        $query = 'SELECT signalement_id, description FROM suivi WHERE description LIKE "Le signalement a été cloturé pour tous les partenaires avec le motif suivant%"';
path: migrations/Version20250401111532.php
user: login: numew
body: Vu que c'est juste l'accent qui change la requête reste valide
created_at: 2025-04-03T13:36:00Z
author_association: COLLABORATOR
diff_hunk: @@ -41,6 +41,7 @@ class SignalementExportSelectableColumns
         'DERNIERE_MAJ' => ['name' => 'Dernière MAJ le', 'description' => 'La date de la dernière mise à jour du signalement', 'export' => 'modifiedAt'],
         'DATE_CLOTURE' => ['name' => 'Fermé le', 'description' => 'La date de clôture du signalement', 'export' => 'closedAt'],
         'MOTIF_CLOTURE' => ['name' => 'Motif de clôture', 'description' => 'Le motif de clôture du signalement', 'export' => 'motifCloture'],
+        'COM_CLOTURE' => ['name' => 'Commentaire de clôture', 'description' => 'Le commentaire de clôture du signalement', 'export' => 'comCloture'],
path: src/Service/Signalement/Export/SignalementExportSelectableColumns.php
user: login: hmeneuvrier
body: Il manque un en-tête de colonne : 
![image](https://github.com/user-attachments/assets/3c4964c0-73b8-4413-a88e-772dd564f912)

created_at: 2025-04-07T08:01:18Z
author_association: COLLABORATOR
diff_hunk: @@ -41,6 +41,7 @@ class SignalementExportSelectableColumns
         'DERNIERE_MAJ' => ['name' => 'Dernière MAJ le', 'description' => 'La date de la dernière mise à jour du signalement', 'export' => 'modifiedAt'],
         'DATE_CLOTURE' => ['name' => 'Fermé le', 'description' => 'La date de clôture du signalement', 'export' => 'closedAt'],
         'MOTIF_CLOTURE' => ['name' => 'Motif de clôture', 'description' => 'Le motif de clôture du signalement', 'export' => 'motifCloture'],
+        'COM_CLOTURE' => ['name' => 'Commentaire de clôture', 'description' => 'Le commentaire de clôture du signalement', 'export' => 'comCloture'],
path: src/Service/Signalement/Export/SignalementExportSelectableColumns.php
user: login: hmeneuvrier
body: à ajouter dans src/Service/Signalement/Export/SignalementExportHeader.php
created_at: 2025-04-07T08:02:49Z
author_association: COLLABORATOR
diff_hunk: @@ -41,6 +41,7 @@ class SignalementExportSelectableColumns
         'DERNIERE_MAJ' => ['name' => 'Dernière MAJ le', 'description' => 'La date de la dernière mise à jour du signalement', 'export' => 'modifiedAt'],
         'DATE_CLOTURE' => ['name' => 'Fermé le', 'description' => 'La date de clôture du signalement', 'export' => 'closedAt'],
         'MOTIF_CLOTURE' => ['name' => 'Motif de clôture', 'description' => 'Le motif de clôture du signalement', 'export' => 'motifCloture'],
+        'COM_CLOTURE' => ['name' => 'Commentaire de clôture', 'description' => 'Le commentaire de clôture du signalement', 'export' => 'comCloture'],
path: src/Service/Signalement/Export/SignalementExportSelectableColumns.php
user: login: numew
body: Ok, merci
created_at: 2025-04-08T08:33:32Z
author_association: COLLABORATOR

PR comments:
user: login: hmeneuvrier
created_at: 2025-04-07T08:39:03Z
body: J'ai testé sur la base de prod. La migration est bien effectuée pas de souci. Par contre, je ne reçois pas l'export, je reçois des mails d'erreur de ce type : 
![image](https://github.com/user-attachments/assets/3e11a5ec-8453-4903-9c37-c621141d1e65)

Et je n'ai pas réussi à comprendre pourquoi, ni même à savoir si c'était important. Je préfère le signaler quand même.
author_association: COLLABORATOR
user: login: sonarqubecloud[bot]
created_at: 2025-04-08T08:33:23Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=MTES-MCT_histologe&pullRequest=3928) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [4.7% Duplication on New Code](https://sonarcloud.io/component_measures?id=MTES-MCT_histologe&pullRequest=3928&metric=new_duplicated_lines_density&view=list) (required ≤ 3%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=MTES-MCT_histologe&pullRequest=3928)


author_association: NONE