diff --git a/src/ApplicationInstallations/UseCase/InstallContactPerson/Handler.php b/src/ApplicationInstallations/UseCase/InstallContactPerson/Handler.php index 7f2e4666..2e09a908 100644 --- a/src/ApplicationInstallations/UseCase/InstallContactPerson/Handler.php +++ b/src/ApplicationInstallations/UseCase/InstallContactPerson/Handler.php @@ -37,18 +37,19 @@ public function handle(Command $command): void ]); $createdContactPersonId = ''; - - try { - if (null !== $command->mobilePhoneNumber) { - try { - $this->guardMobilePhoneNumber($command->mobilePhoneNumber); - } catch (InvalidArgumentException) { - // Ошибка уже залогирована внутри гарда. - // Прерываем создание контакта, но не останавливаем установку приложения. - return; - } + $mobilePhoneNumber = $command->mobilePhoneNumber; + + if (null !== $mobilePhoneNumber) { + try { + $this->guardMobilePhoneNumber($mobilePhoneNumber); + } catch (InvalidArgumentException) { + // Ошибка уже залогирована внутри гарда. + // Отбрасываем невалидный номер: контакт создаётся без мобильного телефона. + $mobilePhoneNumber = null; } + } + try { $applicationInstallation = $this->applicationInstallationRepository->getById($command->applicationInstallationId); assert($applicationInstallation instanceof AggregateRootEventsEmitterInterface); @@ -61,7 +62,7 @@ public function handle(Command $command): void $command->fullName, $command->email, null, - $command->mobilePhoneNumber, + $mobilePhoneNumber, null, $command->comment, $command->externalId, diff --git a/src/Console/ApplicationSettingsListCommand.php b/src/Console/ApplicationSettingsListCommand.php index abda2403..0f308421 100644 --- a/src/Console/ApplicationSettingsListCommand.php +++ b/src/Console/ApplicationSettingsListCommand.php @@ -4,7 +4,6 @@ namespace Bitrix24\Lib\Console; -use Bitrix24\Lib\ApplicationSettings\Entity\ApplicationSettingsItemInterface; use Bitrix24\Lib\ApplicationSettings\Infrastructure\Doctrine\ApplicationSettingsItemRepositoryInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -131,13 +130,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $allSettings = $this->applicationSettingRepository->findAllForInstallation($installationId); if ($globalOnly || (null === $userId && null === $departmentId)) { - $settings = array_filter($allSettings, fn (ApplicationSettingsItemInterface $setting): bool => $setting->isGlobal()); + $settings = array_filter($allSettings, fn ($setting): bool => $setting->isGlobal()); $scope = 'Global'; } elseif (null !== $userId) { - $settings = array_filter($allSettings, fn (ApplicationSettingsItemInterface $setting): bool => $setting->isPersonal() && $setting->getB24UserId() === $userId); + $settings = array_filter($allSettings, fn ($setting): bool => $setting->isPersonal() && $setting->getB24UserId() === $userId); $scope = sprintf('Personal (User ID: %d)', $userId); } else { - $settings = array_filter($allSettings, fn (ApplicationSettingsItemInterface $setting): bool => $setting->isDepartmental() && $setting->getB24DepartmentId() === $departmentId); + $settings = array_filter($allSettings, fn ($setting): bool => $setting->isDepartmental() && $setting->getB24DepartmentId() === $departmentId); $scope = sprintf('Departmental (Department ID: %d)', $departmentId); } diff --git a/tests/Contract/ApplicationSettings/Infrastructure/ApplicationSettingsItemRepositoryInterfaceContractTest.php b/tests/Contract/ApplicationSettings/Infrastructure/ApplicationSettingsItemRepositoryInterfaceContractTest.php index e4f1ec40..1dfdd08f 100644 --- a/tests/Contract/ApplicationSettings/Infrastructure/ApplicationSettingsItemRepositoryInterfaceContractTest.php +++ b/tests/Contract/ApplicationSettings/Infrastructure/ApplicationSettingsItemRepositoryInterfaceContractTest.php @@ -299,6 +299,7 @@ public function testFindAllForInstallationByKeyReturnsEmptyArrayForNonExistentKe $results = $this->repository->findAllForInstallationByKey($uuidV7, 'non.existent.key'); + $this->assertIsArray($results); $this->assertEmpty($results); } @@ -373,7 +374,7 @@ public function testRepositoryHandlesDifferentScopes(): void $this->assertCount(3, $results); // Verify each scope is present - $values = array_map(fn(\Bitrix24\Lib\ApplicationSettings\Entity\ApplicationSettingsItemInterface $s): string => $s->getValue(), $results); + $values = array_map(fn($s): string => $s->getValue(), $results); $this->assertContains('global', $values); $this->assertContains('personal', $values); $this->assertContains('departmental', $values); diff --git a/tests/Functional/ApplicationInstallations/UseCase/InstallContactPerson/HandlerTest.php b/tests/Functional/ApplicationInstallations/UseCase/InstallContactPerson/HandlerTest.php index 076c62b6..2144b428 100644 --- a/tests/Functional/ApplicationInstallations/UseCase/InstallContactPerson/HandlerTest.php +++ b/tests/Functional/ApplicationInstallations/UseCase/InstallContactPerson/HandlerTest.php @@ -242,6 +242,8 @@ public function testInstallContactPersonWithInvalidPhone(string $phoneNumber, st $this->bitrix24accountRepository->save($bitrix24Account); $applicationInstallation = (new ApplicationInstallationBuilder()) + ->withBitrix24PartnerContactPersonId(null) + ->withContactPersonId(null) ->withBitrix24AccountId($bitrix24Account->getId()) ->withApplicationToken($applicationToken) ->withApplicationStatus(new ApplicationStatus('F')) @@ -274,9 +276,19 @@ public function testInstallContactPersonWithInvalidPhone(string $phoneNumber, st ) ); - // Проверяем, что контакт не был создан + // Контакт создан, но невалидный мобильный телефон отброшен (null) + $dispatchedEvents = $this->eventDispatcher->getOrphanedEvents(); + $this->assertContains(ContactPersonCreatedEvent::class, $dispatchedEvents); + $this->assertContains(ApplicationInstallationContactPersonLinkedEvent::class, $dispatchedEvents); + $foundInstallation = $this->applicationInstallationRepository->getById($applicationInstallation->getId()); - $this->assertNull($foundInstallation->getBitrix24PartnerId()); + $contactPersonId = $foundInstallation->getContactPersonId(); + $this->assertNotNull($contactPersonId); + + $foundContactPerson = $this->repository->getById($contactPersonId); + $this->assertNull($foundContactPerson->getMobilePhone()); + $this->assertSame($contactPerson->getEmail(), $foundContactPerson->getEmail()); + $this->assertEquals($contactPerson->getFullName(), $foundContactPerson->getFullName()); } public static function invalidPhoneProvider(): array diff --git a/tests/Functional/ApplicationSettings/UseCase/Update/HandlerTest.php b/tests/Functional/ApplicationSettings/UseCase/Update/HandlerTest.php index 9db68b8e..778c0d0f 100644 --- a/tests/Functional/ApplicationSettings/UseCase/Update/HandlerTest.php +++ b/tests/Functional/ApplicationSettings/UseCase/Update/HandlerTest.php @@ -121,7 +121,6 @@ public function testCanUpdatePersonalSetting(): void key: 'personal.test', value: 'new_user_value', b24UserId: 123, - b24DepartmentId: null, changedByBitrix24UserId: 456 ); $this->handler->handle($updateCommand); @@ -163,7 +162,6 @@ public function testCanUpdateDepartmentalSetting(): void applicationInstallationId: $uuidV7, key: 'dept.test', value: 'new_dept_value', - b24UserId: null, b24DepartmentId: 456, changedByBitrix24UserId: 789 ); diff --git a/tests/Unit/ApplicationSettings/Services/DefaultSettingsInstallerTest.php b/tests/Unit/ApplicationSettings/Services/DefaultSettingsInstallerTest.php index 85716057..f52443ed 100644 --- a/tests/Unit/ApplicationSettings/Services/DefaultSettingsInstallerTest.php +++ b/tests/Unit/ApplicationSettings/Services/DefaultSettingsInstallerTest.php @@ -18,12 +18,20 @@ #[CoversClass(DefaultSettingsInstaller::class)] class DefaultSettingsInstallerTest extends TestCase { + /** @var Handler&\PHPUnit\Framework\MockObject\MockObject */ + private Handler $createHandler; + + /** @var LoggerInterface&\PHPUnit\Framework\MockObject\MockObject */ private LoggerInterface $logger; + private DefaultSettingsInstaller $service; + #[\Override] protected function setUp(): void { - $this->logger = $this->createStub(LoggerInterface::class); + $this->createHandler = $this->createMock(Handler::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->service = new DefaultSettingsInstaller($this->createHandler, $this->logger); } public function testCanCreateDefaultSettings(): void @@ -33,11 +41,9 @@ public function testCanCreateDefaultSettings(): void 'app.name' => ['value' => 'Test App', 'required' => true], 'app.language' => ['value' => 'ru', 'required' => false], ]; - $createHandler = $this->createMock(Handler::class); - $defaultSettingsInstaller = new DefaultSettingsInstaller($createHandler, $this->logger); // Expect Create Handler to be called twice (once for each setting) - $createHandler->expects($this->exactly(2)) + $this->createHandler->expects($this->exactly(2)) ->method('handle') ->with($this->callback(function (Command $command) use ($uuidV7): bool { // Verify command has correct application installation ID @@ -57,7 +63,7 @@ public function testCanCreateDefaultSettings(): void return false; })); - $defaultSettingsInstaller->createDefaultSettings($uuidV7, $defaultSettings); + $this->service->createDefaultSettings($uuidV7, $defaultSettings); } public function testLogsStartAndFinish(): void @@ -66,24 +72,8 @@ public function testLogsStartAndFinish(): void $defaultSettings = [ 'test.key' => ['value' => 'test', 'required' => false], ]; - $handledCommands = []; - $createHandler = new readonly class( - static function (Command $command) use (&$handledCommands): void { - $handledCommands[] = $command; - } - ) extends Handler { - public function __construct(private \Closure $onHandle) {} - - #[\Override] - public function handle(Command $command): void - { - ($this->onHandle)($command); - } - }; - $logger = $this->createMock(LoggerInterface::class); - $defaultSettingsInstaller = new DefaultSettingsInstaller($createHandler, $logger); - - $logger->expects($this->exactly(2)) + + $this->logger->expects($this->exactly(2)) ->method('info') ->willReturnCallback(function (string $message, array $context) use ($uuidV7): bool { if ('DefaultSettingsInstaller.createDefaultSettings.start' === $message) { @@ -102,14 +92,11 @@ public function handle(Command $command): void return false; }); - $logger->expects($this->once()) + $this->logger->expects($this->once()) ->method('debug') ->with('DefaultSettingsInstaller.settingProcessed', $this->arrayHasKey('key')); - $defaultSettingsInstaller->createDefaultSettings($uuidV7, $defaultSettings); - - $this->assertCount(1, $handledCommands); - $this->assertSame('test.key', $handledCommands[0]->key); + $this->service->createDefaultSettings($uuidV7, $defaultSettings); } public function testCreatesGlobalSettings(): void @@ -118,33 +105,28 @@ public function testCreatesGlobalSettings(): void $defaultSettings = [ 'global.setting' => ['value' => 'value', 'required' => true], ]; - $createHandler = $this->createMock(Handler::class); - $defaultSettingsInstaller = new DefaultSettingsInstaller($createHandler, $this->logger); // Verify that created commands are for global settings (no user/department ID) - $createHandler->expects($this->once()) + $this->createHandler->expects($this->once()) ->method('handle') ->with($this->callback(fn(Command $command): bool => null === $command->b24UserId && null === $command->b24DepartmentId)); - $defaultSettingsInstaller->createDefaultSettings($uuidV7, $defaultSettings); + $this->service->createDefaultSettings($uuidV7, $defaultSettings); } public function testHandlesEmptySettingsArray(): void { $uuidV7 = Uuid::v7(); $defaultSettings = []; - $createHandler = $this->createMock(Handler::class); - $logger = $this->createMock(LoggerInterface::class); - $defaultSettingsInstaller = new DefaultSettingsInstaller($createHandler, $logger); // Create Handler should not be called - $createHandler->expects($this->never()) + $this->createHandler->expects($this->never()) ->method('handle'); // But logging should still happen - $logger->expects($this->exactly(2)) + $this->logger->expects($this->exactly(2)) ->method('info'); - $defaultSettingsInstaller->createDefaultSettings($uuidV7, $defaultSettings); + $this->service->createDefaultSettings($uuidV7, $defaultSettings); } }