diff --git a/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php b/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php index 669248ae0..0b579f637 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php +++ b/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php @@ -15,7 +15,7 @@ use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Gender; use Chill\MainBundle\Entity\GenderEnum; -use Chill\MainBundle\Repository\CenterRepository; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\GenderRepository; use Chill\MainBundle\Repository\PostalCodeRepositoryInterface; use Chill\PersonBundle\Entity\Household\Household; @@ -38,7 +38,7 @@ readonly class PersonUpsertHandler private EntityManagerInterface $entityManager, private MembersEditorFactory $membersEditorFactory, private PostalCodeRepositoryInterface $postalCodeRepository, - private CenterRepository $centerRepository, + private CenterRepositoryInterface $centerRepository, private GenderRepository $genderRepository, private ClockInterface $clock, ) {} diff --git a/src/Bundle/ChillPersonBundle/Tests/Action/Upsert/Handler/PersonUpsertHandlerTest.php b/src/Bundle/ChillPersonBundle/Tests/Action/Upsert/Handler/PersonUpsertHandlerTest.php index 49efb3284..c1b7e66dd 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Action/Upsert/Handler/PersonUpsertHandlerTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Action/Upsert/Handler/PersonUpsertHandlerTest.php @@ -11,14 +11,22 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Action\Upsert\Handler; +use Chill\MainBundle\Entity\Gender; +use Chill\MainBundle\Entity\GenderEnum; +use Chill\MainBundle\Repository\CenterRepositoryInterface; +use Chill\MainBundle\Repository\GenderRepository; +use Chill\MainBundle\Repository\PostalCodeRepositoryInterface; use Chill\PersonBundle\Actions\Upsert\Handler\PersonUpsertHandler; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Identifier\PersonIdentifier; use Chill\PersonBundle\Actions\Upsert\UpsertMessage; +use Chill\PersonBundle\Household\MembersEditor; +use Chill\PersonBundle\Household\MembersEditorFactory; use PHPUnit\Framework\TestCase; use Doctrine\ORM\EntityManagerInterface; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Symfony\Component\Clock\ClockInterface; /** * @internal @@ -29,24 +37,54 @@ class PersonUpsertHandlerTest extends TestCase { use ProphecyTrait; + private function createMembersEditorFactoryMock(): MembersEditorFactory + { + $membersEditor = $this->prophesize(MembersEditor::class); + $membersEditor->validate()->willReturn($this->prophesize(\Doctrine\Common\Collections\Collection::class)->reveal()); + $membersEditor->getPersistable()->willReturn([]); + + $factory = $this->prophesize(MembersEditorFactory::class); + $factory->createEditor()->willReturn($membersEditor->reveal()); + + return $factory->reveal(); + } + public function testInvokeCreatesNewPersonAndIdentifier(): void { $personIdentifierDefinitionRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository::class); $identifierRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository::class); $entityManager = $this->prophesize(EntityManagerInterface::class); + $membersEditorFactory = $this->createMembersEditorFactoryMock(); + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $genderRepository = $this->prophesize(GenderRepository::class); + $clock = $this->prophesize(ClockInterface::class); $definition = $this->prophesize(\Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition::class); $personIdentifierDefinitionRepository->find(1)->willReturn($definition->reveal()); $identifierRepository->findByDefinitionAndCanonical($definition->reveal(), '123')->willReturn([]); - $entityManager->persist(Argument::type(Person::class))->shouldBeCalled(); - $entityManager->persist(Argument::type(PersonIdentifier::class))->shouldBeCalled(); + // Mock gender repository + $gender = $this->prophesize(Gender::class); + $genderRepository->findByGenderTranslation(GenderEnum::NEUTRAL)->willReturn([$gender->reveal()]); + $genderRepository->findByGenderTranslation(Argument::any())->willReturn([$gender->reveal()]); + + // Mock center repository - no center found + $centerRepository->findBy(['name' => null])->willReturn([]); + + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->persist(Argument::any())->shouldBeCalled(); $entityManager->flush()->shouldBeCalled(); $handler = new PersonUpsertHandler( $personIdentifierDefinitionRepository->reveal(), $identifierRepository->reveal(), - $entityManager->reveal() + $entityManager->reveal(), + $membersEditorFactory, + $postalCodeRepository->reveal(), + $centerRepository->reveal(), + $genderRepository->reveal(), + $clock->reveal(), ); $message = new UpsertMessage(); @@ -63,27 +101,47 @@ class PersonUpsertHandlerTest extends TestCase $personIdentifierDefinitionRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository::class); $identifierRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository::class); $entityManager = $this->prophesize(EntityManagerInterface::class); + $membersEditorFactory = $this->createMembersEditorFactoryMock(); + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $genderRepository = $this->prophesize(GenderRepository::class); + $clock = $this->prophesize(ClockInterface::class); $definition = $this->prophesize(\Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition::class); $personIdentifierDefinitionRepository->find(2)->willReturn($definition->reveal()); $person = $this->prophesize(Person::class); - $person->setFirstName('Jane')->shouldBeCalled(); - $person->setLastName('Smith')->shouldBeCalled(); - $person->getFirstName()->willReturn('Jane'); - $person->getLastName()->willReturn('Smith'); + $person->setFirstName('Jane')->shouldBeCalled()->willReturn($person); + $person->setLastName('Smith')->shouldBeCalled()->willReturn($person); + $person->getCurrentHousehold()->willReturn(null); + + $person->setGender(Argument::any())->shouldBeCalled()->willReturn($person); + $person->setCenter(Argument::any())->willReturn($person); $identifier = $this->prophesize(PersonIdentifier::class); $identifier->getPerson()->willReturn($person->reveal()); $identifierRepository->findByDefinitionAndCanonical($definition->reveal(), '456')->willReturn([$identifier->reveal()]); + // Mock gender repository - ensure it always returns an array + $gender = $this->prophesize(Gender::class); + $genderRepository->findByGenderTranslation(GenderEnum::NEUTRAL)->willReturn([$gender->reveal()]); + $genderRepository->findByGenderTranslation(Argument::any())->willReturn([$gender->reveal()]); + + // Mock center repository - no center found + $centerRepository->findBy(['name' => null])->willReturn([]); + $entityManager->flush()->shouldBeCalled(); $handler = new PersonUpsertHandler( $personIdentifierDefinitionRepository->reveal(), $identifierRepository->reveal(), - $entityManager->reveal() + $entityManager->reveal(), + $membersEditorFactory, + $postalCodeRepository->reveal(), + $centerRepository->reveal(), + $genderRepository->reveal(), + $clock->reveal(), ); $message = new UpsertMessage(); @@ -94,4 +152,151 @@ class PersonUpsertHandlerTest extends TestCase $handler->__invoke($message); } + + public function testInvokeWithGenderHandling(): void + { + $personIdentifierDefinitionRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository::class); + $identifierRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository::class); + $entityManager = $this->prophesize(EntityManagerInterface::class); + $membersEditorFactory = $this->createMembersEditorFactoryMock(); + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $genderRepository = $this->prophesize(GenderRepository::class); + $clock = $this->prophesize(ClockInterface::class); + + $definition = $this->prophesize(\Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition::class); + $personIdentifierDefinitionRepository->find(1)->willReturn($definition->reveal()); + $identifierRepository->findByDefinitionAndCanonical($definition->reveal(), '123')->willReturn([]); + + // Mock gender repository - configure to return male gender + $maleGender = $this->prophesize(Gender::class); + $genderRepository->findByGenderTranslation(GenderEnum::MALE)->willReturn([$maleGender->reveal()]); + $genderRepository->findByGenderTranslation(Argument::any())->willReturn([$maleGender->reveal()]); + + // Mock center repository + $centerRepository->findBy(['name' => null])->willReturn([]); + + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->flush()->shouldBeCalled(); + + $handler = new PersonUpsertHandler( + $personIdentifierDefinitionRepository->reveal(), + $identifierRepository->reveal(), + $entityManager->reveal(), + $membersEditorFactory, + $postalCodeRepository->reveal(), + $centerRepository->reveal(), + $genderRepository->reveal(), + $clock->reveal(), + ); + + $message = new UpsertMessage(); + $message->externalId = '123'; + $message->personIdentifierDefinitionId = 1; + $message->firstName = 'John'; + $message->lastName = 'Doe'; + $message->gender = 'male'; + + $handler->__invoke($message); + } + + public function testInvokeWithCenterHandling(): void + { + $personIdentifierDefinitionRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository::class); + $identifierRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository::class); + $entityManager = $this->prophesize(EntityManagerInterface::class); + $membersEditorFactory = $this->createMembersEditorFactoryMock(); + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $genderRepository = $this->prophesize(GenderRepository::class); + $clock = $this->prophesize(ClockInterface::class); + + $definition = $this->prophesize(\Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition::class); + $personIdentifierDefinitionRepository->find(1)->willReturn($definition->reveal()); + $identifierRepository->findByDefinitionAndCanonical($definition->reveal(), '123')->willReturn([]); + + // Mock gender repository + $neutralGender = $this->prophesize(Gender::class); + $genderRepository->findByGenderTranslation(GenderEnum::NEUTRAL)->willReturn([$neutralGender->reveal()]); + $genderRepository->findByGenderTranslation(Argument::any())->willReturn([$neutralGender->reveal()]); + + // Mock center repository - find center by name + $center = $this->prophesize(\Chill\MainBundle\Entity\Center::class); + $centerRepository->findBy(['name' => 'Main Center'])->willReturn([$center->reveal()]); + + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->flush()->shouldBeCalled(); + + $handler = new PersonUpsertHandler( + $personIdentifierDefinitionRepository->reveal(), + $identifierRepository->reveal(), + $entityManager->reveal(), + $membersEditorFactory, + $postalCodeRepository->reveal(), + $centerRepository->reveal(), + $genderRepository->reveal(), + $clock->reveal(), + ); + + $message = new UpsertMessage(); + $message->externalId = '123'; + $message->personIdentifierDefinitionId = 1; + $message->firstName = 'John'; + $message->lastName = 'Doe'; + $message->center = 'Main Center'; + + $handler->__invoke($message); + } + + public function testInvokeWithGenderAndCenterHandling(): void + { + $personIdentifierDefinitionRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository::class); + $identifierRepository = $this->prophesize(\Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository::class); + $entityManager = $this->prophesize(EntityManagerInterface::class); + $membersEditorFactory = $this->createMembersEditorFactoryMock(); + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $genderRepository = $this->prophesize(GenderRepository::class); + $clock = $this->prophesize(ClockInterface::class); + + $definition = $this->prophesize(\Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition::class); + $personIdentifierDefinitionRepository->find(1)->willReturn($definition->reveal()); + $identifierRepository->findByDefinitionAndCanonical($definition->reveal(), '123')->willReturn([]); + + // Mock gender repository - configure to return female gender + $femaleGender = $this->prophesize(Gender::class); + $genderRepository->findByGenderTranslation(GenderEnum::FEMALE)->willReturn([$femaleGender->reveal()]); + $genderRepository->findByGenderTranslation(Argument::any())->willReturn([$femaleGender->reveal()]); + + // Mock center repository - find center by name + $center = $this->prophesize(\Chill\MainBundle\Entity\Center::class); + $centerRepository->findBy(['name' => 'Secondary Center'])->willReturn([$center->reveal()]); + + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->persist(Argument::any())->shouldBeCalled(); + $entityManager->flush()->shouldBeCalled(); + + $handler = new PersonUpsertHandler( + $personIdentifierDefinitionRepository->reveal(), + $identifierRepository->reveal(), + $entityManager->reveal(), + $membersEditorFactory, + $postalCodeRepository->reveal(), + $centerRepository->reveal(), + $genderRepository->reveal(), + $clock->reveal(), + ); + + $message = new UpsertMessage(); + $message->externalId = '123'; + $message->personIdentifierDefinitionId = 1; + $message->firstName = 'Jane'; + $message->lastName = 'Smith'; + $message->gender = 'female'; + $message->center = 'Secondary Center'; + + $handler->__invoke($message); + } }