diff --git a/src/Application/Regulation/Command/CreateRegulationOrderHistoryCommand.php b/src/Application/Regulation/Command/CreateRegulationOrderHistoryCommand.php new file mode 100644 index 000000000..a7600367c --- /dev/null +++ b/src/Application/Regulation/Command/CreateRegulationOrderHistoryCommand.php @@ -0,0 +1,17 @@ +authenticatedUser->getUser()) { + return; + } + + $this->regulationOrderHistoryRepository->add( + new RegulationOrderHistory( + uuid: $this->idFactory->make(), + regulationOrderUuid: $command->regulationOrder->getUuid(), + userUuid: $this->authenticatedUser->getUser()->getUuid(), + action: $command->action, + date: $this->dateUtils->getNow(), + ), + ); + } +} diff --git a/src/Application/Regulation/Command/DeleteRegulationCommandHandler.php b/src/Application/Regulation/Command/DeleteRegulationCommandHandler.php index 950a04adb..cfab439b0 100644 --- a/src/Application/Regulation/Command/DeleteRegulationCommandHandler.php +++ b/src/Application/Regulation/Command/DeleteRegulationCommandHandler.php @@ -4,6 +4,8 @@ namespace App\Application\Regulation\Command; +use App\Application\CommandBusInterface; +use App\Domain\Regulation\Enum\ActionTypeEnum; use App\Domain\Regulation\Exception\RegulationOrderRecordCannotBeDeletedException; use App\Domain\Regulation\Repository\RegulationOrderRepositoryInterface; use App\Domain\Regulation\Specification\CanOrganizationAccessToRegulation; @@ -13,17 +15,21 @@ final class DeleteRegulationCommandHandler public function __construct( private RegulationOrderRepositoryInterface $regulationOrderRepository, private CanOrganizationAccessToRegulation $canOrganizationAccessToRegulation, + private CommandBusInterface $commandBus, ) { } public function __invoke(DeleteRegulationCommand $command): void { $regulationOrderRecord = $command->regulationOrderRecord; + $regulationOrder = $regulationOrderRecord->getRegulationOrder(); if (false === $this->canOrganizationAccessToRegulation->isSatisfiedBy($regulationOrderRecord, $command->userOrganizationUuids)) { throw new RegulationOrderRecordCannotBeDeletedException(); } - $this->regulationOrderRepository->delete($regulationOrderRecord->getRegulationOrder()); + $this->commandBus->handle(new CreateRegulationOrderHistoryCommand($regulationOrder, ActionTypeEnum::DELETE->value)); + + $this->regulationOrderRepository->delete($regulationOrder); } } diff --git a/src/Application/Regulation/Command/PublishRegulationCommandHandler.php b/src/Application/Regulation/Command/PublishRegulationCommandHandler.php index eec785567..2bb1c56c2 100644 --- a/src/Application/Regulation/Command/PublishRegulationCommandHandler.php +++ b/src/Application/Regulation/Command/PublishRegulationCommandHandler.php @@ -4,6 +4,8 @@ namespace App\Application\Regulation\Command; +use App\Application\CommandBusInterface; +use App\Domain\Regulation\Enum\ActionTypeEnum; use App\Domain\Regulation\Enum\RegulationOrderRecordStatusEnum; use App\Domain\Regulation\Exception\RegulationOrderRecordCannotBePublishedException; use App\Domain\Regulation\Specification\CanRegulationOrderRecordBePublished; @@ -12,6 +14,7 @@ final class PublishRegulationCommandHandler { public function __construct( private CanRegulationOrderRecordBePublished $canRegulationOrderRecordBePublished, + private CommandBusInterface $commandBus, ) { } @@ -21,6 +24,10 @@ public function __invoke(PublishRegulationCommand $command): void throw new RegulationOrderRecordCannotBePublishedException(); } + $regulationOrder = $command->regulationOrderRecord->getRegulationOrder(); + + $this->commandBus->handle(new CreateRegulationOrderHistoryCommand($regulationOrder, ActionTypeEnum::PUBLISH->value)); + $command->regulationOrderRecord->updateStatus(RegulationOrderRecordStatusEnum::PUBLISHED->value); } } diff --git a/src/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandler.php b/src/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandler.php index 2a565d53e..b4f51bd4d 100644 --- a/src/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandler.php +++ b/src/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandler.php @@ -4,9 +4,11 @@ namespace App\Application\Regulation\Command; +use App\Application\CommandBusInterface; use App\Application\IdFactoryInterface; use App\Application\Organization\VisaModel\Query\GetVisaModelQuery; use App\Application\QueryBusInterface; +use App\Domain\Regulation\Enum\ActionTypeEnum; use App\Domain\Regulation\Enum\RegulationOrderRecordStatusEnum; use App\Domain\Regulation\RegulationOrder; use App\Domain\Regulation\RegulationOrderRecord; @@ -21,6 +23,7 @@ public function __construct( private RegulationOrderRecordRepositoryInterface $regulationOrderRecordRepository, private \DateTimeInterface $now, private QueryBusInterface $queryBus, + private CommandBusInterface $commandBus, ) { } @@ -57,11 +60,16 @@ public function __invoke(SaveRegulationGeneralInfoCommand $command): RegulationO ), ); + $this->commandBus->handle(new CreateRegulationOrderHistoryCommand($regulationOrder, ActionTypeEnum::CREATE->value)); + return $regulationOrderRecord; } $command->regulationOrderRecord->updateOrganization($command->organization); - $command->regulationOrderRecord->getRegulationOrder()->update( + + $regulationOrder = $command->regulationOrderRecord->getRegulationOrder(); + + $regulationOrder->update( identifier: $command->identifier, category: $command->category, subject: $command->subject, @@ -72,6 +80,8 @@ public function __invoke(SaveRegulationGeneralInfoCommand $command): RegulationO visaModel: $visaModel, ); + $this->commandBus->handle(new CreateRegulationOrderHistoryCommand($regulationOrder, ActionTypeEnum::UPDATE->value)); + return $command->regulationOrderRecord; } } diff --git a/src/Domain/Regulation/Enum/ActionTypeEnum.php b/src/Domain/Regulation/Enum/ActionTypeEnum.php new file mode 100644 index 000000000..6381e990c --- /dev/null +++ b/src/Domain/Regulation/Enum/ActionTypeEnum.php @@ -0,0 +1,13 @@ +uuid; + } + + public function getRegulationOrderUuid(): string + { + return $this->regulationOrderUuid; + } + + public function getUserUuid(): string + { + return $this->userUuid; + } + + public function getAction(): string + { + return $this->action; + } + + public function getDate(): \DateTimeInterface + { + return $this->date; + } +} diff --git a/src/Domain/Regulation/Repository/RegulationOrderHistoryRepositoryInterface.php b/src/Domain/Regulation/Repository/RegulationOrderHistoryRepositoryInterface.php new file mode 100644 index 000000000..5e18a0c7f --- /dev/null +++ b/src/Domain/Regulation/Repository/RegulationOrderHistoryRepositoryInterface.php @@ -0,0 +1,12 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Infrastructure/Persistence/Doctrine/Migrations/Version20250116114330.php b/src/Infrastructure/Persistence/Doctrine/Migrations/Version20250116114330.php new file mode 100644 index 000000000..8b801ac73 --- /dev/null +++ b/src/Infrastructure/Persistence/Doctrine/Migrations/Version20250116114330.php @@ -0,0 +1,32 @@ +addSql('CREATE TABLE regulation_order_history (uuid UUID NOT NULL, regulation_order_uuid VARCHAR(50) NOT NULL, user_uuid VARCHAR(50) NOT NULL, action VARCHAR(20) NOT NULL, date TIMESTAMP(0) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY(uuid))'); + $this->addSql('CREATE INDEX IDX_E47F415B267E0D5E ON regulation_order_history (regulation_order_uuid)'); + $this->addSql('CREATE INDEX IDX_E47F415BABFE1C6F ON regulation_order_history (user_uuid)'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP TABLE regulation_order_history'); + } +} diff --git a/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderHistoryRepository.php b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderHistoryRepository.php new file mode 100644 index 000000000..fb1608463 --- /dev/null +++ b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderHistoryRepository.php @@ -0,0 +1,25 @@ +getEntityManager()->persist($regulationOrderHistory); + + return $regulationOrderHistory; + } +} diff --git a/tests/Unit/Application/Regulation/Command/CreateRegulationOrderHistoryCommandHandlerTest.php b/tests/Unit/Application/Regulation/Command/CreateRegulationOrderHistoryCommandHandlerTest.php new file mode 100644 index 000000000..aafcdb99e --- /dev/null +++ b/tests/Unit/Application/Regulation/Command/CreateRegulationOrderHistoryCommandHandlerTest.php @@ -0,0 +1,93 @@ +idFactory = $this->createMock(IdFactoryInterface::class); + $this->regulationOrderHistoryRepository = $this->createMock(RegulationOrderHistoryRepositoryInterface::class); + $this->dateUtils = $this->createMock(DateUtilsInterface::class); + $this->authenticatedUser = $this->createMock(AuthenticatedUser::class); + } + + public function testCreate(): void + { + $now = new \DateTimeImmutable('2023-06-13'); + + $this->dateUtils + ->expects(self::once()) + ->method('getNow') + ->willReturn($now); + + $this->idFactory + ->expects(self::once()) + ->method('make') + ->willReturn('d035fec0-30f3-4134-95b9-d74c68eb53e3'); + + $regulationOrder = $this->createMock(RegulationOrder::class); + $user = $this->createMock(User::class); + $action = ActionTypeEnum::PUBLISH->value; + + $regulationOrder + ->expects(self::once()) + ->method('getUuid') + ->willReturn('9ddd73e5-2162-4279-be73-183816e7f85b'); + + $this->authenticatedUser + ->expects(self::exactly(2)) + ->method('getUser') + ->willReturn($user); + + $user + ->expects(self::once()) + ->method('getUuid') + ->willReturn('3cc78eae-50ba-4805-9b75-7f64ca638caf'); + + $this->regulationOrderHistoryRepository + ->expects(self::once()) + ->method('add') + ->with( + $this->equalTo( + new RegulationOrderHistory( + uuid: 'd035fec0-30f3-4134-95b9-d74c68eb53e3', + regulationOrderUuid: '9ddd73e5-2162-4279-be73-183816e7f85b', + userUuid: '3cc78eae-50ba-4805-9b75-7f64ca638caf', + action: $action, + date: $now, + ), + ), + ); + + $handler = new CreateRegulationOrderHistoryCommandHandler( + $this->idFactory, + $this->regulationOrderHistoryRepository, + $this->dateUtils, + $this->authenticatedUser, + ); + + $command = new CreateRegulationOrderHistoryCommand($regulationOrder, $action); + + $handler($command); + } +} diff --git a/tests/Unit/Application/Regulation/Command/DeleteRegulationCommandHandlerTest.php b/tests/Unit/Application/Regulation/Command/DeleteRegulationCommandHandlerTest.php index abb7866b0..d2847e584 100644 --- a/tests/Unit/Application/Regulation/Command/DeleteRegulationCommandHandlerTest.php +++ b/tests/Unit/Application/Regulation/Command/DeleteRegulationCommandHandlerTest.php @@ -4,6 +4,7 @@ namespace App\Tests\Unit\Application\Regulation\Command; +use App\Application\CommandBusInterface; use App\Application\Regulation\Command\DeleteRegulationCommand; use App\Application\Regulation\Command\DeleteRegulationCommandHandler; use App\Domain\Regulation\Exception\RegulationOrderRecordCannotBeDeletedException; @@ -12,6 +13,7 @@ use App\Domain\Regulation\Repository\RegulationOrderRepositoryInterface; use App\Domain\Regulation\Specification\CanOrganizationAccessToRegulation; use App\Domain\User\Organization; +use App\Domain\User\User; use PHPUnit\Framework\TestCase; final class DeleteRegulationCommandHandlerTest extends TestCase @@ -21,6 +23,7 @@ final class DeleteRegulationCommandHandlerTest extends TestCase private $regulationOrderRepository; private $regulationOrderRecord; private $regulationOrder; + private $commandBus; protected function setUp(): void { @@ -29,11 +32,13 @@ protected function setUp(): void $this->regulationOrderRepository = $this->createMock(RegulationOrderRepositoryInterface::class); $this->regulationOrderRecord = $this->createMock(RegulationOrderRecord::class); $this->regulationOrder = $this->createMock(RegulationOrder::class); + $this->commandBus = $this->createMock(CommandBusInterface::class); } public function testDelete(): void { $organization = $this->createMock(Organization::class); + $user = $this->createMock(User::class); $this->canOrganizationAccessToRegulation ->expects(self::once()) @@ -53,7 +58,7 @@ public function testDelete(): void $handler = new DeleteRegulationCommandHandler( $this->regulationOrderRepository, - $this->canOrganizationAccessToRegulation, + $this->canOrganizationAccessToRegulation, $this->commandBus, ); $command = new DeleteRegulationCommand($this->organizationUuids, $this->regulationOrderRecord); @@ -77,12 +82,13 @@ public function testCannotDelete(): void ->method('delete'); $this->regulationOrderRecord - ->expects(self::never()) + ->expects(self::once()) ->method('getRegulationOrder'); $handler = new DeleteRegulationCommandHandler( $this->regulationOrderRepository, $this->canOrganizationAccessToRegulation, + $this->commandBus, ); $command = new DeleteRegulationCommand($this->organizationUuids, $this->regulationOrderRecord); diff --git a/tests/Unit/Application/Regulation/Command/PublishRegulationCommandHandlerTest.php b/tests/Unit/Application/Regulation/Command/PublishRegulationCommandHandlerTest.php index 7c4b875a8..f66ad31d5 100644 --- a/tests/Unit/Application/Regulation/Command/PublishRegulationCommandHandlerTest.php +++ b/tests/Unit/Application/Regulation/Command/PublishRegulationCommandHandlerTest.php @@ -4,37 +4,62 @@ namespace App\Tests\Unit\Application\Regulation\Command; +use App\Application\CommandBusInterface; +use App\Application\Regulation\Command\CreateRegulationOrderHistoryCommand; use App\Application\Regulation\Command\PublishRegulationCommand; use App\Application\Regulation\Command\PublishRegulationCommandHandler; +use App\Domain\Regulation\Enum\ActionTypeEnum; use App\Domain\Regulation\Exception\RegulationOrderRecordCannotBePublishedException; +use App\Domain\Regulation\RegulationOrder; +use App\Domain\Regulation\RegulationOrderHistory; use App\Domain\Regulation\RegulationOrderRecord; use App\Domain\Regulation\Specification\CanRegulationOrderRecordBePublished; +use App\Domain\User\User; use PHPUnit\Framework\TestCase; final class PublishRegulationCommandHandlerTest extends TestCase { private $canRegulationOrderRecordBePublished; + private $commandBus; protected function setUp(): void { $this->canRegulationOrderRecordBePublished = $this->createMock(CanRegulationOrderRecordBePublished::class); + $this->commandBus = $this->createMock(CommandBusInterface::class); } public function testPublish(): void { + $createdRegulationOrderHistory = $this->createMock(RegulationOrderHistory::class); + $regulationOrder = $this->createMock(RegulationOrder::class); + $user = $this->createMock(User::class); $regulationOrderRecord = $this->createMock(RegulationOrderRecord::class); + $regulationOrderRecord ->expects(self::once()) ->method('updateStatus') ->with('published'); + $regulationOrderRecord + ->expects(self::once()) + ->method('getRegulationOrder') + ->willReturn($regulationOrder); + $this->canRegulationOrderRecordBePublished ->expects(self::once()) ->method('isSatisfiedBy') ->willReturn(true); + $action = ActionTypeEnum::PUBLISH->value; + $regulationOrderHistoryCommand = new CreateRegulationOrderHistoryCommand($regulationOrder, $action); + + $this->commandBus + ->expects(self::once()) + ->method('handle') + ->with($this->equalTo($regulationOrderHistoryCommand)); + $handler = new PublishRegulationCommandHandler( - $this->canRegulationOrderRecordBePublished, + $this->canRegulationOrderRecordBePublished, $this->commandBus, ); $command = new PublishRegulationCommand($regulationOrderRecord); @@ -57,7 +82,7 @@ public function testRegulationCannotBePublished(): void ->willReturn(false); $handler = new PublishRegulationCommandHandler( - $this->canRegulationOrderRecordBePublished, + $this->canRegulationOrderRecordBePublished, $this->commandBus, ); $command = new PublishRegulationCommand($regulationOrderRecord); diff --git a/tests/Unit/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandlerTest.php b/tests/Unit/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandlerTest.php index ae60202d7..df93dc4de 100644 --- a/tests/Unit/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandlerTest.php +++ b/tests/Unit/Application/Regulation/Command/SaveRegulationGeneralInfoCommandHandlerTest.php @@ -4,12 +4,15 @@ namespace App\Tests\Unit\Application\Regulation\Command; +use App\Application\CommandBusInterface; use App\Application\IdFactoryInterface; use App\Application\Organization\VisaModel\Query\GetVisaModelQuery; use App\Application\QueryBusInterface; +use App\Application\Regulation\Command\CreateRegulationOrderHistoryCommand; use App\Application\Regulation\Command\SaveRegulationGeneralInfoCommand; use App\Application\Regulation\Command\SaveRegulationGeneralInfoCommandHandler; use App\Domain\Organization\VisaModel\VisaModel; +use App\Domain\Regulation\Enum\ActionTypeEnum; use App\Domain\Regulation\Enum\RegulationOrderCategoryEnum; use App\Domain\Regulation\Enum\RegulationOrderRecordSourceEnum; use App\Domain\Regulation\Enum\RegulationOrderRecordStatusEnum; @@ -19,6 +22,7 @@ use App\Domain\Regulation\Repository\RegulationOrderRecordRepositoryInterface; use App\Domain\Regulation\Repository\RegulationOrderRepositoryInterface; use App\Domain\User\Organization; +use App\Domain\User\User; use PHPUnit\Framework\TestCase; final class SaveRegulationGeneralInfoCommandHandlerTest extends TestCase @@ -29,6 +33,8 @@ final class SaveRegulationGeneralInfoCommandHandlerTest extends TestCase private $queryBus; private $organization; private $visaModel; + private $commandBus; + private $user; public function setUp(): void { @@ -38,6 +44,8 @@ public function setUp(): void $this->queryBus = $this->createMock(QueryBusInterface::class); $this->organization = $this->createMock(Organization::class); $this->visaModel = $this->createMock(VisaModel::class); + $this->commandBus = $this->createMock(CommandBusInterface::class); + $this->user = $this->createMock(User::class); } public function testCreate(): void @@ -98,6 +106,7 @@ public function testCreate(): void $this->regulationOrderRecordRepository, $now, $this->queryBus, + $this->commandBus, ); $command = new SaveRegulationGeneralInfoCommand(); @@ -165,12 +174,19 @@ public function testUpdate(): void ->method('updateOrganization') ->with($organization); + $regulationOrderHistoryCommand = new CreateRegulationOrderHistoryCommand($regulationOrder, ActionTypeEnum::UPDATE->value); + + $this->commandBus + ->expects(self::once()) + ->method('handle') + ->with($this->equalTo($regulationOrderHistoryCommand)); $handler = new SaveRegulationGeneralInfoCommandHandler( $this->idFactory, $this->regulationOrderRepository, $this->regulationOrderRecordRepository, $now, $this->queryBus, + $this->commandBus, ); $command = new SaveRegulationGeneralInfoCommand($regulationOrderRecord); diff --git a/tests/Unit/Domain/Regulation/RegulationOrderHistoryTest.php b/tests/Unit/Domain/Regulation/RegulationOrderHistoryTest.php new file mode 100644 index 000000000..e0db7de82 --- /dev/null +++ b/tests/Unit/Domain/Regulation/RegulationOrderHistoryTest.php @@ -0,0 +1,30 @@ +value, + date: $date, + ); + + $this->assertSame('6598fd41-85cb-42a6-9693-1bc45f4dd392', $regulationOrderHistory->getUuid()); + $this->assertSame('f518b777-aa4e-4e8e-852b-15a64c849198', $regulationOrderHistory->getRegulationOrderUuid()); + $this->assertSame('6659bfb5-1e51-4000-99de-68e3d9a90a69', $regulationOrderHistory->getUserUuid()); + $this->assertSame('create', $regulationOrderHistory->getAction()); + $this->assertSame($date, $regulationOrderHistory->getDate()); + } +}