diff --git a/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php b/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php index 5d938e1d2..4b6bc96ea 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php +++ b/src/Bundle/ChillPersonBundle/Actions/Upsert/Handler/PersonUpsertHandler.php @@ -11,11 +11,18 @@ declare(strict_types=1); namespace Chill\PersonBundle\Actions\Upsert\Handler; +use Chill\MainBundle\Entity\Address; +use Chill\MainBundle\Repository\PostalCodeRepositoryInterface; +use Chill\PersonBundle\Entity\Household\Household; +use Chill\PersonBundle\Household\MembersEditorFactory; +use Chill\PersonBundle\Repository\Household\PositionRepository; use Chill\PersonBundle\Repository\Identifier\PersonIdentifierDefinitionRepository; use Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Identifier\PersonIdentifier; use Chill\PersonBundle\Actions\Upsert\UpsertMessage; +use Symfony\Component\Clock\Clock; +use Symfony\Component\Clock\ClockInterface; use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Doctrine\ORM\EntityManagerInterface; @@ -26,10 +33,105 @@ readonly class PersonUpsertHandler private PersonIdentifierDefinitionRepository $personIdentifierDefinitionRepository, private PersonIdentifierRepository $personIdentifierRepository, private EntityManagerInterface $entityManager, + private MembersEditorFactory $membersEditorFactory, + private PostalCodeRepositoryInterface $postalCodeRepository, + private PositionRepository $positionRepository, + private ClockInterface $clock, ) {} - private function _handlePersonMessage(UpsertMessage $message, Person $person): Person + private function createAddressWithMessage(UpsertMessage $message): Address { + $newAddress = new Address(); + if (null !== $message->address) { + $newAddress->setStreet($message->address); + } + if (null !== $message->streetNumber) { + $newAddress->setStreetNumber($message->streetNumber); + } + if (null !== $message->postcode) { + $postalCode = $this->postalCodeRepository->findOneBy(['code' => $message->postcode]); + if (null !== $postalCode) { + $newAddress->setPostcode($postalCode); + } + } + if (null !== $message->extra) { + $newAddress->setExtra($message->extra); + } + $newAddress->setValidFrom(\DateTime::createFromImmutable($this->clock->now())); + + return $newAddress; + + } + + private function messageAddressExistsAddresses(array $currentAddresses, UpsertMessage $message): bool + { + foreach ($currentAddresses as $existingAddress) { + $streetMatches = $message->address === $existingAddress->getStreet(); + $streetNumberMatches = $message->streetNumber === $existingAddress->getStreetNumber(); + $postcodeMatches = null !== $existingAddress->getPostcode() + && $message->postcode === $existingAddress->getPostcode()->getCode(); + + if ($streetMatches && $streetNumberMatches && $postcodeMatches) { + return true; + } + } + + return false; + } + + private function handlePersonMessage(UpsertMessage $message, Person $person): Person + { + $membersEditor = $this->membersEditorFactory->createEditor(); + $currentHousehold = $person->getCurrentHousehold(); + + // Check if address information is provided in the message + $hasAddressInfo = $message->hasAddressInfo(); + + if (null !== $currentHousehold && $hasAddressInfo) { + $currentAddresses = $currentHousehold->getAddresses()->toArray(); + $addressMatches = $this->messageAddressExistsAddresses($currentAddresses, $message); + + if (!$addressMatches) { + $newAddress = $this->createAddressWithMessage($message); + $currentHousehold->addAddress($newAddress); + } + } elseif (null === $currentHousehold && $hasAddressInfo) { + // Create a new household with a new address + $newHousehold = new Household(); + + // Create the new address + $newAddress = $this->createAddressWithMessage($message); + $newHousehold->addAddress($newAddress); + + // Find a default position (first one ordered by ordering) + $positions = $this->positionRepository->findByActiveOrdered(); + $defaultPosition = count($positions) > 0 ? $positions[0] : null; + + // Create a MembersEditor with the new household and add the person + $membersEditor = $this->membersEditorFactory->createEditor($newHousehold); + $membersEditor->addMovement( + $this->clock->now(), + $person, + $defaultPosition, + true + ); + + // Validate the membership + $violations = $membersEditor->validate(); + if ($violations->count() > 0) { + // Handle validation errors - for now we'll just skip household creation + // In production, you might want to log this or throw an exception + } else { + // Persist the household and trigger events + $this->entityManager->persist($newHousehold); + foreach ($membersEditor->getPersistable() as $persistable) { + $this->entityManager->persist($persistable); + } + $membersEditor->postMove(); + } + } + + // Update person information if (null !== $message->firstName) { $person->setFirstName($message->firstName); } @@ -37,6 +139,7 @@ readonly class PersonUpsertHandler $person->setLastName($message->lastName); } + // @todo add gender and center return $person; } @@ -58,7 +161,7 @@ readonly class PersonUpsertHandler if (0 === count($identifiers)) { // 3. Create new entity Person $person = new Person(); - $person = $this->_handlePersonMessage($message, $person); + $person = $this->handlePersonMessage($message, $person); $this->entityManager->persist($person); // Create and bound identifier @@ -71,7 +174,7 @@ readonly class PersonUpsertHandler /** @var PersonIdentifier $identifier */ $identifier = $identifiers[0]; $person = $identifier->getPerson(); - $person = $this->_handlePersonMessage($message, $person); + $person = $this->handlePersonMessage($message, $person); } $this->entityManager->flush(); diff --git a/src/Bundle/ChillPersonBundle/Actions/Upsert/UpsertMessage.php b/src/Bundle/ChillPersonBundle/Actions/Upsert/UpsertMessage.php index a90dffa32..63b0d5efc 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Upsert/UpsertMessage.php +++ b/src/Bundle/ChillPersonBundle/Actions/Upsert/UpsertMessage.php @@ -26,4 +26,9 @@ class UpsertMessage public ?string $streetNumber = null; public ?string $postcode = null; public ?string $city = null; + + public function hasAddressInfo(): bool + { + return null !== $this->address || null !== $this->postcode || null !== $this->streetNumber; + } }