Skip to content

Commit

Permalink
Merge pull request #2432 from MTES-MCT/hotfix/2326-bo-suppression-sui…
Browse files Browse the repository at this point in the history
…vi-for-SA

 [BO] POssibilité de supprimer les suivis pour les SA
  • Loading branch information
numew committed Apr 10, 2024
2 parents e89b7a5 + 1906141 commit 823bde1
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 8 deletions.
30 changes: 30 additions & 0 deletions migrations/Version20240410075332.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

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

final class Version20240410075332 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add deleted_at and deleted_by_id on suivi';
}

public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE suivi ADD deleted_by_id INT DEFAULT NULL, ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
$this->addSql('ALTER TABLE suivi ADD CONSTRAINT FK_2EBCCA8FC76F1F52 FOREIGN KEY (deleted_by_id) REFERENCES user (id)');
$this->addSql('CREATE INDEX IDX_2EBCCA8FC76F1F52 ON suivi (deleted_by_id)');
}

public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE suivi DROP FOREIGN KEY FK_2EBCCA8FC76F1F52');
$this->addSql('DROP INDEX IDX_2EBCCA8FC76F1F52 ON suivi');
$this->addSql('ALTER TABLE suivi DROP deleted_by_id, DROP deleted_at');
}
}
7 changes: 5 additions & 2 deletions public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,11 @@ document?.querySelectorAll('[data-delete]')?.forEach(actionBtn => {
body: formData,
}).then(r => {
if (r.ok) {
actionBtn.closest(className).remove()
if (event.target.classList.contains('partner-row-delete')) {
if (className && className !== undefined && className !== null){
actionBtn?.closest(className).remove()
}
if (event.target.classList.contains('partner-row-delete')
|| event.target.classList.contains('suivi-row-delete')) {
window.location.reload(true)
}
}
Expand Down
35 changes: 34 additions & 1 deletion src/Controller/Back/SignalementActionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Entity\Suivi;
use App\Entity\Tag;
use App\Entity\User;
use App\Repository\SuiviRepository;
use App\Service\Mailer\NotificationMail;
use App\Service\Mailer\NotificationMailerRegistry;
use App\Service\Mailer\NotificationMailerType;
Expand All @@ -20,6 +21,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[Route('/bo/signalements')]
class SignalementActionController extends AbstractController
Expand Down Expand Up @@ -114,7 +116,38 @@ public function addSuiviSignalement(
$this->addFlash('error', 'Une erreur est survenu lors de la publication');
}

return $this->redirect($this->generateUrl('back_signalement_view', ['uuid' => $signalement->getUuid()]).'#suivis');
return $this->redirect(
$this->generateUrl('back_signalement_view', ['uuid' => $signalement->getUuid()]).'#suivis'
);
}

#[Route('/{uuid}/suivi/delete', name: 'back_signalement_delete_suivi', methods: 'POST')]
#[IsGranted('ROLE_ADMIN')]
public function deleteSuivi(
Request $request,
Signalement $signalement,
SuiviRepository $suiviRepository,
ManagerRegistry $doctrine,
): RedirectResponse {
if ($this->isCsrfTokenValid('signalement_delete_suivi_'.$signalement->getId(), $request->get('_token'))
&& $idSuivi = $request->get('suivi')
) {
$suivi = $suiviRepository->findOneBy(['id' => $idSuivi]);
if ($suivi) {
$suivi->setDeletedAt(new DateTimeImmutable());
$suivi->setDeletedBy($this->getUser());
$doctrine->getManager()->persist($suivi);
$doctrine->getManager()->flush();

$this->addFlash('success', 'Le suivi a été supprimé.');
} else {
$this->addFlash('success', 'Ce suivi n\'existe pas.');
}
}

return $this->redirect(
$this->generateUrl('back_signalement_view', ['uuid' => $signalement->getUuid()]).'#suivis'
);
}

#[Route('/{uuid}/reopen', name: 'back_signalement_reopen')]
Expand Down
36 changes: 36 additions & 0 deletions src/Entity/Suivi.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Suivi
public const DESCRIPTION_MOTIF_CLOTURE_ALL = 'Le signalement a été cloturé pour tous';
public const DESCRIPTION_MOTIF_CLOTURE_PARTNER = 'Le signalement a été cloturé pour';
public const DESCRIPTION_SIGNALEMENT_VALIDE = 'Signalement validé';
public const DESCRIPTION_DELETED = 'Ce suivi a été supprimé par un administrateur le ';

public const ARRET_PROCEDURE = 'arret-procedure';
public const POURSUIVRE_PROCEDURE = 'poursuivre-procedure';
Expand Down Expand Up @@ -56,6 +57,13 @@ class Suivi

private bool $sendMail = true;

#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $deletedAt;

#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(nullable: true)]
private $deletedBy;

public function __construct()
{
$this->createdAt = new DateTimeImmutable();
Expand Down Expand Up @@ -93,6 +101,10 @@ public function setCreatedBy(?User $createdBy): self

public function getDescription(): ?string
{
if (null !== $this->deletedAt) {
return self::DESCRIPTION_DELETED.' '.$this->deletedAt->format('d/m/Y');
}

return $this->description;
}

Expand Down Expand Up @@ -162,4 +174,28 @@ public function setSendMail(bool $sendMail): self

return $this;
}

public function getDeletedAt(): ?DateTimeImmutable
{
return $this->deletedAt;
}

public function setDeletedAt(DateTimeImmutable $deletedAt): self
{
$this->deletedAt = $deletedAt;

return $this;
}

public function getDeletedBy(): ?User
{
return $this->deletedBy;
}

public function setDeletedBy(?User $deletedBy): self
{
$this->deletedBy = $deletedBy;

return $this;
}
}
13 changes: 9 additions & 4 deletions src/Security/Voter/SuiviVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $
{
/** @var User $user */
$user = $token->getUser();
if (!$user instanceof UserInterface || !$user->isSuperAdmin() && $subject->getTerritory() !== $user->getTerritory()) {
if (
!$user instanceof UserInterface
|| !$user->isSuperAdmin()
&& $subject->getTerritory() !== $user->getTerritory()
) {
return false;
}
if ($user->isSuperAdmin()) {
Expand All @@ -41,9 +45,10 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $

private function canCreate(Signalement $signalement, User $user): bool
{
return Signalement::STATUS_ACTIVE === $signalement->getStatut() && $signalement->getAffectations()->filter(function (Affectation $affectation) use ($user) {
return $affectation->getPartner()->getId() === $user->getPartner()->getId();
})->count() > 0 || $user->isTerritoryAdmin();
return Signalement::STATUS_ACTIVE === $signalement->getStatut()
&& $signalement->getAffectations()->filter(function (Affectation $affectation) use ($user) {
return $affectation->getPartner()->getId() === $user->getPartner()->getId();
})->count() > 0 || $user->isTerritoryAdmin();
}

private function canView(mixed $comment, User $user): bool
Expand Down
16 changes: 15 additions & 1 deletion templates/back/signalement/view/suivis.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@
{% endif %}
</div>

<div class="fr-col-7 bloc-suivi-content-row fr-pl-3v">
{% if is_granted('ROLE_ADMIN') %}
<div class="fr-col-6 bloc-suivi-content-row fr-pl-3v">
{% else %}
<div class="fr-col-7 bloc-suivi-content-row fr-pl-3v">
{% endif %}
{{ suivi.description
|replace({'&t=___TOKEN___':'/'~signalement.uuid})
|replace({'?t=___TOKEN___':'/'~signalement.uuid})
Expand All @@ -74,6 +78,16 @@
<span class="fr-badge fr-badge--no-icon" title="Suivi interne">Suivi interne</span>
{% endif %}
</div>
{% if is_granted('ROLE_ADMIN') %}
<div class="fr-col-1 fr-text--right">
{% if suivi.deletedAt is null %}
<button title="Supprimer le suivi"
data-delete="{{ path('back_signalement_delete_suivi',{uuid:signalement.uuid,suivi:suivi.id}) }}"
data-token="{{ csrf_token('signalement_delete_suivi_'~signalement.id) }}"
class="fr-btn fr-btn--sm fr-btn--secondary fr-fi-delete-line suivi-row-delete"></button>
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\Tests\Functional\Controller\Back;

use App\Entity\Suivi;
use App\Repository\SignalementRepository;
use App\Repository\SuiviRepository;
use App\Repository\UserRepository;
use App\Tests\SessionHelper;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Routing\RouterInterface;

class SignalementActionControllerTest extends WebTestCase
{
use SessionHelper;

private ?KernelBrowser $client = null;
private UserRepository $userRepository;
private SignalementRepository $signalementRepository;
private SuiviRepository $suiviRepository;
private RouterInterface $router;

protected function setUp(): void
{
$this->client = static::createClient();
$this->router = self::getContainer()->get(RouterInterface::class);
$this->userRepository = static::getContainer()->get(UserRepository::class);
$this->suiviRepository = static::getContainer()->get(SuiviRepository::class);
$this->signalementRepository = static::getContainer()->get(SignalementRepository::class);

$user = $this->userRepository->findOneBy(['email' => 'admin-01@histologe.fr']);
$this->client->loginUser($user);
}

public function testDeleteSuivi(): void
{
$signalement = $this->signalementRepository->findOneBy(['uuid' => '00000000-0000-0000-2023-000000000006']);

$route = $this->router->generate('back_signalement_delete_suivi', ['uuid' => $signalement->getUuid()]);
$this->client->request('GET', $route);

$description = 'Un petit message de rappel afin d\'y revenir plus tard';
$suivi = $this->suiviRepository->findOneBy(['description' => $description]);

$this->client->request(
'POST',
$route,
[
'suivi' => $suivi->getId(),
'_token' => $this->generateCsrfToken($this->client, 'signalement_delete_suivi_'.$signalement->getId()),
]
);

$suivi = $this->suiviRepository->findOneBy(['description' => $description]);
$this->assertNotNull($suivi->getDeletedAt());
$this->assertNotNull($suivi->getDeletedBy());
$this->assertNotEquals($description, $suivi->getDescription());
$this->assertStringContainsString(Suivi::DESCRIPTION_DELETED, $suivi->getDescription());
$this->assertResponseRedirects('/bo/signalements/'.$signalement->getUuid().'#suivis');
}
}

0 comments on commit 823bde1

Please sign in to comment.