From f38c459e21c9a2930cfec77afde2f7bf2fbdbbdf Mon Sep 17 00:00:00 2001 From: Mathieu MARCHOIS Date: Thu, 7 Nov 2024 15:18:15 +0100 Subject: [PATCH] Signing authority form (#1047) --- .../SaveSigningAuthorityCommand.xml | 28 +++++ public/images/signing_authority.png | Bin 0 -> 10423 bytes .../Command/SaveSigningAuthorityCommand.php | 27 +++++ .../SaveSigningAuthorityCommandHandler.php | 43 ++++++++ ...GetSigningAuthorityByOrganizationQuery.php | 15 +++ ...ingAuthorityByOrganizationQueryHandler.php | 21 ++++ .../SigningAuthorityRepositoryInterface.php | 14 +++ .../SigningAuthority/SigningAuthority.php | 12 +++ .../EditSigningAuthorityController.php | 78 ++++++++++++++ .../Organization/SigningAuthorityFormType.php | 58 ++++++++++ .../SigningAuthorityRepository.php | 36 +++++++ .../my_area/organization/_menu.html.twig | 6 +- .../signing_authority/form.html.twig | 44 ++++++++ .../EditSigningAuthorityControllerTest.php | 98 +++++++++++++++++ ...SaveSigningAuthorityCommandHandlerTest.php | 99 ++++++++++++++++++ ...uthorityByOrganizationQueryHandlerTest.php | 31 ++++++ .../DeleteVisaModelCommandHandlerTest.php | 2 +- .../DuplicateVisaModelCommandHandlerTest.php | 2 +- .../SaveVisaModelCommandHandlerTest.php | 2 +- .../Query/GetVisaModelQueryHandlerTest.php | 2 +- .../Query/GetVisaModelsQueryHandlerTest.php | 2 +- .../Unit/Domain/User/SigningAuthorityTest.php | 12 +++ translations/messages.fr.xlf | 40 +++++++ 23 files changed, 665 insertions(+), 7 deletions(-) create mode 100644 config/validator/Application/SigningAuthority/SaveSigningAuthorityCommand.xml create mode 100644 public/images/signing_authority.png create mode 100644 src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommand.php create mode 100644 src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandler.php create mode 100644 src/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQuery.php create mode 100644 src/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQueryHandler.php create mode 100644 src/Domain/Organization/SigningAuthority/Repository/SigningAuthorityRepositoryInterface.php create mode 100644 src/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityController.php create mode 100644 src/Infrastructure/Form/Organization/SigningAuthorityFormType.php create mode 100644 src/Infrastructure/Persistence/Doctrine/Repository/SigningAuthority/SigningAuthorityRepository.php create mode 100644 templates/my_area/organization/signing_authority/form.html.twig create mode 100644 tests/Integration/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityControllerTest.php create mode 100644 tests/Unit/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandlerTest.php create mode 100644 tests/Unit/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQueryHandlerTest.php rename tests/Unit/Application/{ => Organization}/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php (97%) rename tests/Unit/Application/{ => Organization}/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php (97%) rename tests/Unit/Application/{ => Organization}/VisaModel/Command/SaveVisaModelCommandHandlerTest.php (97%) rename tests/Unit/Application/{ => Organization}/VisaModel/Query/GetVisaModelQueryHandlerTest.php (96%) rename tests/Unit/Application/{ => Organization}/VisaModel/Query/GetVisaModelsQueryHandlerTest.php (96%) diff --git a/config/validator/Application/SigningAuthority/SaveSigningAuthorityCommand.xml b/config/validator/Application/SigningAuthority/SaveSigningAuthorityCommand.xml new file mode 100644 index 000000000..14ca8ab13 --- /dev/null +++ b/config/validator/Application/SigningAuthority/SaveSigningAuthorityCommand.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/signing_authority.png b/public/images/signing_authority.png new file mode 100644 index 0000000000000000000000000000000000000000..fbde9e482bbb4309ef84f7b574b5d83964118f66 GIT binary patch literal 10423 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 literal 0 HcmV?d00001 diff --git a/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommand.php b/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommand.php new file mode 100644 index 000000000..8955b14ff --- /dev/null +++ b/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommand.php @@ -0,0 +1,27 @@ +name = $signingAuthority?->getName(); + $this->address = $signingAuthority?->getAddress(); + $this->placeOfSignature = $signingAuthority?->getPlaceOfSignature(); + $this->signatoryName = $signingAuthority?->getSignatoryName(); + } +} diff --git a/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandler.php b/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandler.php new file mode 100644 index 000000000..2792a9d94 --- /dev/null +++ b/src/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandler.php @@ -0,0 +1,43 @@ +signingAuthority) { + $signingAuthority->update( + name: $command->name, + address: $command->address, + placeOfSignature: $command->placeOfSignature, + signatoryName: $command->signatoryName, + ); + + return $signingAuthority; + } + + return $this->signingAuthorityRepository->add( + new SigningAuthority( + uuid: $this->idFactory->make(), + name: $command->name, + address: $command->address, + placeOfSignature: $command->placeOfSignature, + signatoryName: $command->signatoryName, + organization: $command->organization, + ), + ); + } +} diff --git a/src/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQuery.php b/src/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQuery.php new file mode 100644 index 000000000..bd95c8b4e --- /dev/null +++ b/src/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQuery.php @@ -0,0 +1,15 @@ +signingAuthorityRepository->findOneByOrganizationUuid($query->organizationUuid); + } +} diff --git a/src/Domain/Organization/SigningAuthority/Repository/SigningAuthorityRepositoryInterface.php b/src/Domain/Organization/SigningAuthority/Repository/SigningAuthorityRepositoryInterface.php new file mode 100644 index 000000000..f888d174d --- /dev/null +++ b/src/Domain/Organization/SigningAuthority/Repository/SigningAuthorityRepositoryInterface.php @@ -0,0 +1,14 @@ +organization; } + + public function update( + string $name, + string $address, + string $placeOfSignature, + string $signatoryName, + ): void { + $this->name = $name; + $this->address = $address; + $this->placeOfSignature = $placeOfSignature; + $this->signatoryName = $signatoryName; + } } diff --git a/src/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityController.php b/src/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityController.php new file mode 100644 index 000000000..5fe9ff4a2 --- /dev/null +++ b/src/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityController.php @@ -0,0 +1,78 @@ + Requirement::UUID], + methods: ['GET', 'POST'], + )] + public function __invoke(Request $request, string $uuid): Response + { + $organization = $this->getOrganization($uuid); + + if (!$this->security->isGranted(OrganizationVoter::EDIT, $organization)) { + throw new AccessDeniedHttpException(); + } + + $signingAuthority = $this->queryBus->handle(new GetSigningAuthorityByOrganizationQuery($uuid)); + $command = new SaveSigningAuthorityCommand($organization, $signingAuthority); + $form = $this->formFactory->create(SigningAuthorityFormType::class, $command); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->commandBus->handle($command); + + return new RedirectResponse( + url: $this->router->generate('app_config_signing_authority_edit', ['uuid' => $uuid]), + status: Response::HTTP_SEE_OTHER, + ); + } + + return new Response( + content: $this->twig->render( + name: 'my_area/organization/signing_authority/form.html.twig', + context: [ + 'organization' => $organization, + 'form' => $form->createView(), + ], + ), + status: ($form->isSubmitted() && !$form->isValid()) + ? Response::HTTP_UNPROCESSABLE_ENTITY + : Response::HTTP_OK, + ); + } +} diff --git a/src/Infrastructure/Form/Organization/SigningAuthorityFormType.php b/src/Infrastructure/Form/Organization/SigningAuthorityFormType.php new file mode 100644 index 000000000..1671449c7 --- /dev/null +++ b/src/Infrastructure/Form/Organization/SigningAuthorityFormType.php @@ -0,0 +1,58 @@ +add( + 'name', + TextType::class, + options: [ + 'label' => 'signing_authority.name', + 'help' => 'signing_authority.name.help', + ], + ) + ->add( + 'address', + TextareaType::class, + options: [ + 'label' => 'signing_authority.address', + 'help' => 'signing_authority.address.help', + ], + ) + ->add( + 'placeOfSignature', + TextType::class, + options: [ + 'label' => 'signing_authority.placeOfSignature', + 'help' => 'signing_authority.placeOfSignature.help', + ], + ) + ->add( + 'signatoryName', + TextType::class, + options: [ + 'label' => 'signing_authority.signatoryName', + 'help' => 'signing_authority.signatoryName.help', + ], + ) + ->add('save', SubmitType::class, + options: [ + 'label' => 'common.save', + 'attr' => ['class' => 'fr-btn'], + ], + ) + ; + } +} diff --git a/src/Infrastructure/Persistence/Doctrine/Repository/SigningAuthority/SigningAuthorityRepository.php b/src/Infrastructure/Persistence/Doctrine/Repository/SigningAuthority/SigningAuthorityRepository.php new file mode 100644 index 000000000..e27346b0f --- /dev/null +++ b/src/Infrastructure/Persistence/Doctrine/Repository/SigningAuthority/SigningAuthorityRepository.php @@ -0,0 +1,36 @@ +getEntityManager()->persist($signingAuthority); + + return $signingAuthority; + } + + public function findOneByOrganizationUuid(string $organizationUuid): ?SigningAuthority + { + return $this->createQueryBuilder('s') + ->where('s.organization = :uuid') + ->setParameter('uuid', $organizationUuid) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult() + ; + } +} diff --git a/templates/my_area/organization/_menu.html.twig b/templates/my_area/organization/_menu.html.twig index d7b4a180c..d618aa285 100644 --- a/templates/my_area/organization/_menu.html.twig +++ b/templates/my_area/organization/_menu.html.twig @@ -17,7 +17,7 @@
  • - + diff --git a/templates/my_area/organization/signing_authority/form.html.twig b/templates/my_area/organization/signing_authority/form.html.twig new file mode 100644 index 000000000..25d501656 --- /dev/null +++ b/templates/my_area/organization/signing_authority/form.html.twig @@ -0,0 +1,44 @@ +{% extends 'layouts/layout.html.twig' %} +{% set metaTitle = 'signing_authority.form.title'|trans %} +{% block title %} + {{ metaTitle }} - {{ parent() }} +{% endblock %} + +{% block body %} +
    +
    +
    + {% include 'my_area/organization/_menu.html.twig' with { organization } only %} +
    +
    + {% include "common/breadcrumb.html.twig" with { items: [ + { title: 'user.myarea'|trans, path: 'app_my_area'}, + { title: organization.name, url: path('app_config_organization_detail', {uuid: organization.uuid}), generatedPath: true }, + { title: metaTitle }, + ]} %} +

    {{ metaTitle }}

    + {{ form_start(form) }} +
    +
    + {{ form_row(form.name, { group_class: 'fr-input-group', widget_class: 'fr-input' }) }} + {{ form_row(form.address, { group_class: 'fr-input-group', widget_class: 'fr-input' }) }} + {{ form_row(form.placeOfSignature, { group_class: 'fr-input-group', widget_class: 'fr-input' }) }} + {{ form_row(form.signatoryName, { group_class: 'fr-input-group', widget_class: 'fr-input' }) }} +
    +
    +
    + {% set imageTitle = 'signing_authority.form.image_description'|trans %} +
    {{ imageTitle }}
    + {{ imageTitle }} +
    +
    +
    + + {{ "common.cancel"|trans }} + + {{ form_widget(form.save) }} + {{ form_end(form) }} +
    +
    +
    +{% endblock %} diff --git a/tests/Integration/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityControllerTest.php b/tests/Integration/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityControllerTest.php new file mode 100644 index 000000000..ab5d6309f --- /dev/null +++ b/tests/Integration/Infrastructure/Controller/MyArea/Organization/SigningAuthority/EditSigningAuthorityControllerTest.php @@ -0,0 +1,98 @@ +login('mathieu.fernandez@beta.gouv.fr'); + $crawler = $client->request('GET', '/mon-espace/organizations/' . OrganizationFixture::MAIN_ORG_ID . '/signing_authority/edit'); + + $this->assertResponseStatusCodeSame(200); + $this->assertSecurityHeaders(); + $this->assertSame('Autorité signataire', $crawler->filter('h2')->text()); + $this->assertMetaTitle('Autorité signataire - DiaLog', $crawler); + + $saveButton = $crawler->selectButton('Sauvegarder'); + $form = $saveButton->form(); + + // Get the raw values. + $values = $form->getPhpValues(); + $values['signing_authority_form']['name'] = 'Madame la maire de Pau'; + $values['signing_authority_form']['address'] = '3 rue de la Concertation'; + $values['signing_authority_form']['signatoryName'] = 'Madame X, maire de Pau'; + $values['signing_authority_form']['placeOfSignature'] = 'Savenay'; + + $crawler = $client->request($form->getMethod(), $form->getUri(), $values, $form->getPhpFiles()); + $client->followRedirect(); + + $this->assertResponseStatusCodeSame(200); + $this->assertRouteSame('app_config_signing_authority_edit'); + } + + public function testBadFormValues(): void + { + $client = $this->login('mathieu.fernandez@beta.gouv.fr'); + $crawler = $client->request('GET', '/mon-espace/organizations/' . OrganizationFixture::MAIN_ORG_ID . '/signing_authority/edit'); + + $saveButton = $crawler->selectButton('Sauvegarder'); + $form = $saveButton->form(); + + // Get the raw values. + $values = $form->getPhpValues(); + $values['signing_authority_form']['name'] = ''; + $values['signing_authority_form']['address'] = ''; + $values['signing_authority_form']['signatoryName'] = ''; + $values['signing_authority_form']['placeOfSignature'] = ''; + $crawler = $client->request($form->getMethod(), $form->getUri(), $values, $form->getPhpFiles()); + + $this->assertResponseStatusCodeSame(422); + $this->assertSame('Cette valeur ne doit pas être vide.', $crawler->filter('#signing_authority_form_name_error')->text()); + $this->assertSame('Cette valeur ne doit pas être vide.', $crawler->filter('#signing_authority_form_address_error')->text()); + $this->assertSame('Cette valeur ne doit pas être vide.', $crawler->filter('#signing_authority_form_placeOfSignature_error')->text()); + $this->assertSame('Cette valeur ne doit pas être vide.', $crawler->filter('#signing_authority_form_signatoryName_error')->text()); + + $values['signing_authority_form']['name'] = str_repeat('a', 101); + $values['signing_authority_form']['signatoryName'] = str_repeat('a', 101); + $values['signing_authority_form']['placeOfSignature'] = str_repeat('a', 101); + $crawler = $client->request($form->getMethod(), $form->getUri(), $values, $form->getPhpFiles()); + $this->assertResponseStatusCodeSame(422); + $this->assertSame('Cette chaîne est trop longue. Elle doit avoir au maximum 100 caractères.', $crawler->filter('#signing_authority_form_name_error')->text()); + $this->assertSame('Cette chaîne est trop longue. Elle doit avoir au maximum 100 caractères.', $crawler->filter('#signing_authority_form_placeOfSignature_error')->text()); + $this->assertSame('Cette chaîne est trop longue. Elle doit avoir au maximum 100 caractères.', $crawler->filter('#signing_authority_form_signatoryName_error')->text()); + } + + public function testNotAdministrator(): void + { + $client = $this->login(); + $client->request('GET', '/mon-espace/organizations/' . OrganizationFixture::MAIN_ORG_ID . '/signing_authority/edit'); + $this->assertResponseStatusCodeSame(403); + } + + public function testOrganizationNotOwned(): void + { + $client = $this->login(); + $client->request('GET', '/mon-espace/organizations/' . OrganizationFixture::OTHER_ORG_ID . '/signing_authority/edit'); + $this->assertResponseStatusCodeSame(403); + } + + public function testOrganizationOrUserNotFound(): void + { + $client = $this->login(); + $client->request('GET', '/mon-espace/organizations/f5c1cea8-a61d-43a7-9b5d-4b8c9557c673/signing_authority/edit'); + $this->assertResponseStatusCodeSame(404); + } + + public function testWithoutAuthenticatedUser(): void + { + $client = static::createClient(); + $client->request('GET', '/mon-espace/organizations/' . OrganizationFixture::MAIN_ORG_ID . '/signing_authority/edit'); + $this->assertResponseRedirects('http://localhost/login', 302); + } +} diff --git a/tests/Unit/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandlerTest.php b/tests/Unit/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandlerTest.php new file mode 100644 index 000000000..4edc52d83 --- /dev/null +++ b/tests/Unit/Application/Organization/SigningAuthority/Command/SaveSigningAuthorityCommandHandlerTest.php @@ -0,0 +1,99 @@ +idFactory = $this->createMock(IdFactoryInterface::class); + $this->signingAuthorityRepository = $this->createMock(SigningAuthorityRepositoryInterface::class); + } + + public function testAdd(): void + { + $organization = $this->createMock(Organization::class); + + $signingAuthority = new SigningAuthority( + uuid: '9cebe00d-04d8-48da-89b1-059f6b7bfe44', + name: 'Monsieur le maire de Savenay', + address: '3 rue de la Concertation', + placeOfSignature: 'Savenay', + signatoryName: 'Monsieur X, Maire de Savenay', + organization: $organization, + ); + + $this->signingAuthorityRepository + ->expects(self::once()) + ->method('add') + ->with($signingAuthority) + ->willReturn($signingAuthority); + + $this->idFactory + ->expects(self::once()) + ->method('make') + ->willReturn('9cebe00d-04d8-48da-89b1-059f6b7bfe44'); + + $handler = new SaveSigningAuthorityCommandHandler( + $this->idFactory, + $this->signingAuthorityRepository, + ); + $command = new SaveSigningAuthorityCommand($organization); + $command->name = 'Monsieur le maire de Savenay'; + $command->address = '3 rue de la Concertation'; + $command->placeOfSignature = 'Savenay'; + $command->signatoryName = 'Monsieur X, Maire de Savenay'; + + $handler($command); + } + + public function testUpdate(): void + { + $organization = $this->createMock(Organization::class); + $signingAuthority = $this->createMock(SigningAuthority::class); + $signingAuthority + ->expects(self::once()) + ->method('update') + ->with( + 'Madame la maire de Savenay', + '4 rue de la Concertation', + 'Savenay', + 'Madame X, Maire de Savenay', + ); + + $this->signingAuthorityRepository + ->expects(self::never()) + ->method('add'); + + $this->idFactory + ->expects(self::never()) + ->method('make'); + + $handler = new SaveSigningAuthorityCommandHandler( + $this->idFactory, + $this->signingAuthorityRepository, + ); + + $command = new SaveSigningAuthorityCommand($organization, $signingAuthority); + $command->name = 'Madame la maire de Savenay'; + $command->address = '4 rue de la Concertation'; + $command->placeOfSignature = 'Savenay'; + $command->signatoryName = 'Madame X, Maire de Savenay'; + + $handler($command); + } +} diff --git a/tests/Unit/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQueryHandlerTest.php b/tests/Unit/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQueryHandlerTest.php new file mode 100644 index 000000000..473627e64 --- /dev/null +++ b/tests/Unit/Application/Organization/SigningAuthority/Query/GetSigningAuthorityByOrganizationQueryHandlerTest.php @@ -0,0 +1,31 @@ +createMock(SigningAuthority::class); + + $signingAuthorityRepository = $this->createMock(SigningAuthorityRepositoryInterface::class); + $signingAuthorityRepository + ->expects(self::once()) + ->method('findOneByOrganizationUuid') + ->with('3d1c6ec7-28f5-4b6b-be71-b0920e85b4bf') + ->willReturn($signingAuthority); + + $handler = new GetSigningAuthorityByOrganizationQueryHandler($signingAuthorityRepository); + $result = $handler(new GetSigningAuthorityByOrganizationQuery('3d1c6ec7-28f5-4b6b-be71-b0920e85b4bf')); + + $this->assertEquals($signingAuthority, $result); + } +} diff --git a/tests/Unit/Application/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php b/tests/Unit/Application/Organization/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php similarity index 97% rename from tests/Unit/Application/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php rename to tests/Unit/Application/Organization/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php index b0a7f71c9..27666f046 100644 --- a/tests/Unit/Application/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php +++ b/tests/Unit/Application/Organization/VisaModel/Command/DeleteVisaModelCommandHandlerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Tests\Unit\Application\VisaModel\Command; +namespace App\Tests\Unit\Application\Organization\VisaModel\Command; use App\Application\Organization\VisaModel\Command\DeleteVisaModelCommand; use App\Application\Organization\VisaModel\Command\DeleteVisaModelCommandHandler; diff --git a/tests/Unit/Application/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php b/tests/Unit/Application/Organization/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php similarity index 97% rename from tests/Unit/Application/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php rename to tests/Unit/Application/Organization/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php index b4620bffb..73b57a1f9 100644 --- a/tests/Unit/Application/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php +++ b/tests/Unit/Application/Organization/VisaModel/Command/DuplicateVisaModelCommandHandlerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Tests\Unit\Application\VisaModel\Command; +namespace App\Tests\Unit\Application\Organization\VisaModel\Command; use App\Application\CommandBusInterface; use App\Application\Organization\VisaModel\Command\DuplicateVisaModelCommand; diff --git a/tests/Unit/Application/VisaModel/Command/SaveVisaModelCommandHandlerTest.php b/tests/Unit/Application/Organization/VisaModel/Command/SaveVisaModelCommandHandlerTest.php similarity index 97% rename from tests/Unit/Application/VisaModel/Command/SaveVisaModelCommandHandlerTest.php rename to tests/Unit/Application/Organization/VisaModel/Command/SaveVisaModelCommandHandlerTest.php index c515cf6a5..0409e816f 100644 --- a/tests/Unit/Application/VisaModel/Command/SaveVisaModelCommandHandlerTest.php +++ b/tests/Unit/Application/Organization/VisaModel/Command/SaveVisaModelCommandHandlerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Tests\Unit\Application\VisaModel\Command; +namespace App\Tests\Unit\Application\Organization\VisaModel\Command; use App\Application\IdFactoryInterface; use App\Application\Organization\VisaModel\Command\SaveVisaModelCommand; diff --git a/tests/Unit/Application/VisaModel/Query/GetVisaModelQueryHandlerTest.php b/tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelQueryHandlerTest.php similarity index 96% rename from tests/Unit/Application/VisaModel/Query/GetVisaModelQueryHandlerTest.php rename to tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelQueryHandlerTest.php index b79587930..950d5057f 100644 --- a/tests/Unit/Application/VisaModel/Query/GetVisaModelQueryHandlerTest.php +++ b/tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelQueryHandlerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Tests\Unit\Application\VisaModel\Query; +namespace App\Tests\Unit\Application\Organization\VisaModel\Query; use App\Application\Organization\VisaModel\Query\GetVisaModelQuery; use App\Application\Organization\VisaModel\Query\GetVisaModelQueryHandler; diff --git a/tests/Unit/Application/VisaModel/Query/GetVisaModelsQueryHandlerTest.php b/tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelsQueryHandlerTest.php similarity index 96% rename from tests/Unit/Application/VisaModel/Query/GetVisaModelsQueryHandlerTest.php rename to tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelsQueryHandlerTest.php index c7b4f0934..558a1641b 100644 --- a/tests/Unit/Application/VisaModel/Query/GetVisaModelsQueryHandlerTest.php +++ b/tests/Unit/Application/Organization/VisaModel/Query/GetVisaModelsQueryHandlerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace App\Tests\Unit\Application\VisaModel\Query; +namespace App\Tests\Unit\Application\Organization\VisaModel\Query; use App\Application\Organization\VisaModel\Query\GetVisaModelsQuery; use App\Application\Organization\VisaModel\Query\GetVisaModelsQueryHandler; diff --git a/tests/Unit/Domain/User/SigningAuthorityTest.php b/tests/Unit/Domain/User/SigningAuthorityTest.php index d520a47f7..5437e458e 100644 --- a/tests/Unit/Domain/User/SigningAuthorityTest.php +++ b/tests/Unit/Domain/User/SigningAuthorityTest.php @@ -29,5 +29,17 @@ public function testGetters(): void $this->assertSame('Savenay', $signatoryAuthority->getPlaceOfSignature()); $this->assertSame('Monsieur X, Maire de Savenay', $signatoryAuthority->getSignatoryName()); $this->assertSame('3 rue de la Concertation', $signatoryAuthority->getAddress()); + + $signatoryAuthority->update( + name: 'Madame la maire de Savenay', + address: '4 rue de la Concertation', + placeOfSignature: 'Savenay 2', + signatoryName: 'Madame X, Maire de Savenay', + ); + + $this->assertSame('Madame la maire de Savenay', $signatoryAuthority->getName()); + $this->assertSame('Savenay 2', $signatoryAuthority->getPlaceOfSignature()); + $this->assertSame('Madame X, Maire de Savenay', $signatoryAuthority->getSignatoryName()); + $this->assertSame('4 rue de la Concertation', $signatoryAuthority->getAddress()); } } diff --git a/translations/messages.fr.xlf b/translations/messages.fr.xlf index ac7f9f956..3847e157c 100644 --- a/translations/messages.fr.xlf +++ b/translations/messages.fr.xlf @@ -2516,6 +2516,46 @@ visa.list.duplicate Duppliquer le modèle "%name%" + + signing_authority.form.title + Autorité signataire + + + signing_authority.name + Intitulé du signataire + + + signing_authority.name.help + Entrez l'intitulé du signataire, par exemple "Madame le maire de XX" + + + signing_authority.address + Adresse de l'établissement + + + signing_authority.address.help + Entrez l'adresse de l'établissement, par exemple de la mairie + + + signing_authority.placeOfSignature + Fait à + + + signing_authority.placeOfSignature.help + Entrez le nom de la ville ou a été rédigé l'arrếté + + + signing_authority.signatoryName + Nom du signataire + + + signing_authority.signatoryName.help + Entrez le nom du signataire de l'arrếté + + + signing_authority.form.image_description + Vue d'ensemble schématique de l’arrêté montrant l’emplacement des informations sur l’autorité signataire. +