-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
1,084 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace DoctrineMigrations; | ||
|
||
use Doctrine\DBAL\Schema\Schema; | ||
use Doctrine\Migrations\AbstractMigration; | ||
|
||
final class Version20250130150909 extends AbstractMigration | ||
{ | ||
public function getDescription(): string | ||
{ | ||
return 'Add uuid column to affectation table'; | ||
} | ||
|
||
public function up(Schema $schema): void | ||
{ | ||
$this->addSql('ALTER TABLE affectation ADD uuid VARCHAR(255) NOT NULL AFTER territory_id'); | ||
$this->addSql('UPDATE affectation SET uuid = UUID()'); | ||
} | ||
|
||
public function down(Schema $schema): void | ||
{ | ||
$this->addSql('ALTER TABLE affectation DROP uuid'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
<?php | ||
|
||
namespace App\Controller\Api; | ||
|
||
use App\Dto\Api\Request\AffectationRequest; | ||
use App\Dto\Api\Response\AffectationResponse; | ||
use App\Entity\Affectation; | ||
use App\Entity\Enum\AffectationNewStatus; | ||
use App\Entity\Enum\MotifCloture; | ||
use App\Entity\Enum\MotifRefus; | ||
use App\Entity\User; | ||
use App\EventListener\SecurityApiExceptionListener; | ||
use App\Exception\Suivi\UsagerNotificationRequiredException; | ||
use App\Manager\AffectationManager; | ||
use App\Security\Voter\AffectationVoter; | ||
use OpenApi\Attributes as OA; | ||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||
use Symfony\Component\DependencyInjection\Attribute\When; | ||
use Symfony\Component\HttpFoundation\JsonResponse; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; | ||
use Symfony\Component\Routing\Attribute\Route; | ||
|
||
#[When('dev')] | ||
#[When('test')] | ||
#[Route('/api')] | ||
class AffectationUpdateController extends AbstractController | ||
{ | ||
public function __construct(private readonly AffectationManager $affectationManager) | ||
{ | ||
} | ||
|
||
/** | ||
* @throws UsagerNotificationRequiredException | ||
*/ | ||
#[Route('/affectations/{uuid:affectation}', name: 'api_affectations_update', methods: 'PATCH')] | ||
#[OA\Patch( | ||
path: '/api/affectations/{uuid}', | ||
description: 'Mise à jour d\'une affectation', | ||
summary: 'Mise à jour d\'une affectation', | ||
security: [['Bearer' => []]], | ||
tags: ['Affectations'], | ||
)] | ||
#[OA\Response( | ||
response: Response::HTTP_OK, | ||
description: 'Une affectation', | ||
content: new OA\JsonContent(ref: '#/components/schemas/Affectation') | ||
)] | ||
#[OA\Response( | ||
response: Response::HTTP_NOT_FOUND, | ||
description: 'Affectation introuvable', | ||
content: new OA\JsonContent( | ||
properties: [ | ||
new OA\Property( | ||
property: 'message', | ||
type: 'string', | ||
example: 'Affectation introuvable' | ||
), | ||
new OA\Property( | ||
property: 'statut', | ||
type: 'int', | ||
example: Response::HTTP_NOT_FOUND | ||
), | ||
], | ||
type: 'object' | ||
) | ||
)] | ||
#[OA\Response( | ||
response: Response::HTTP_BAD_REQUEST, | ||
description: 'Mauvaise payload (données invalides).', | ||
content: new OA\JsonContent( | ||
properties: [ | ||
new OA\Property( | ||
property: 'message', | ||
type: 'string', | ||
example: 'Valeurs invalides pour les champs suivants :' | ||
), | ||
new OA\Property( | ||
property: 'status', | ||
type: 'integer', | ||
example: 400 | ||
), | ||
new OA\Property( | ||
property: 'errors', | ||
type: 'array', | ||
items: new OA\Items( | ||
properties: [ | ||
new OA\Property( | ||
property: 'property', | ||
type: 'string', | ||
example: 'statut' | ||
), | ||
new OA\Property( | ||
property: 'message', | ||
type: 'string', | ||
example: 'Cette valeur doit être l\'un des choix suivants : \"NOUVEAU\", \"EN_COURS\", \"FERME\", \"REFUSE\"' | ||
), | ||
new OA\Property( | ||
property: 'invalidValue', | ||
type: 'string', | ||
example: 'NOUVEAddU' | ||
), | ||
], | ||
type: 'object' | ||
) | ||
), | ||
], | ||
type: 'object' | ||
) | ||
)] | ||
#[OA\Response( | ||
response: Response::HTTP_FORBIDDEN, | ||
description: 'Accès à la ressource non autorisée.', | ||
content: new OA\JsonContent( | ||
properties: [ | ||
new OA\Property( | ||
property: 'message', | ||
type: 'string', | ||
example: 'Vous n\'avez pas l\'autorisation d\'accéder à cette ressource.' | ||
), | ||
new OA\Property( | ||
property: 'statut', | ||
type: 'int', | ||
example: Response::HTTP_FORBIDDEN | ||
), | ||
], | ||
type: 'object' | ||
) | ||
)] | ||
public function index( | ||
#[MapRequestPayload] AffectationRequest $affectationRequest, | ||
?Affectation $affectation = null, | ||
): JsonResponse { | ||
if (null === $affectation) { | ||
return new JsonResponse( | ||
['message' => 'Affectation introuvable.', 'status' => Response::HTTP_NOT_FOUND], | ||
Response::HTTP_NOT_FOUND | ||
); | ||
} | ||
$affectation->setNextStatut(AffectationNewStatus::mapStatus($affectationRequest->statut)); | ||
$this->denyAccessUnlessGranted(AffectationVoter::ANSWER, $affectation, SecurityApiExceptionListener::ACCESS_DENIED); | ||
$this->denyAccessUnlessGranted(AffectationVoter::UPDATE_STATUT, $affectation, SecurityApiExceptionListener::TRANSITION_STATUT_DENIED); | ||
$this->applyUsagerNotification($affectationRequest, $affectation); | ||
|
||
$affectation = $this->update($affectationRequest, $affectation); | ||
|
||
return new JsonResponse(new AffectationResponse($affectation), Response::HTTP_OK); | ||
} | ||
|
||
private function update(AffectationRequest $affectationRequest, Affectation $affectation): Affectation | ||
{ | ||
/** @var User $user */ | ||
$user = $this->getUser(); | ||
|
||
$statut = AffectationNewStatus::mapStatus($affectationRequest->statut); | ||
if ($statut !== $affectation->getStatut()) { | ||
if (Affectation::STATUS_CLOSED === $statut) { | ||
$motifCloture = MotifCloture::tryFrom($affectationRequest->motifCloture); | ||
|
||
return $this->affectationManager->closeAffectation( | ||
$affectation, | ||
$user, | ||
$motifCloture, | ||
$affectationRequest->message, | ||
true | ||
); | ||
} | ||
$motifRefus = $message = null; | ||
if (Affectation::STATUS_REFUSED === $statut) { | ||
$motifRefus = MotifRefus::tryFrom($affectationRequest->motifRefus)->value; | ||
$message = $affectationRequest->message; | ||
} | ||
|
||
return $this->affectationManager->updateAffectation($affectation, $user, $statut, $motifRefus, $message); | ||
} | ||
|
||
return $affectation; | ||
} | ||
|
||
/** | ||
* @throws UsagerNotificationRequiredException | ||
*/ | ||
private function applyUsagerNotification(AffectationRequest $affectationRequest, Affectation $affectation): void | ||
{ | ||
if (Affectation::STATUS_CLOSED === $affectation->getStatut() | ||
&& Affectation::STATUS_WAIT === $affectation->getNextStatut()) { | ||
if (null === $affectationRequest->notifyUsager) { | ||
throw new UsagerNotificationRequiredException($affectationRequest); | ||
} | ||
|
||
$affectation->setHasNotificationUsagerToCreate($affectationRequest->notifyUsager); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.