diff --git a/src/Module/Directory/Infrastructure/ApiPlatform/State/ConvertProspectProcessor.php b/src/Module/Directory/Infrastructure/ApiPlatform/State/ConvertProspectProcessor.php index 7c62c93..94e5067 100644 --- a/src/Module/Directory/Infrastructure/ApiPlatform/State/ConvertProspectProcessor.php +++ b/src/Module/Directory/Infrastructure/ApiPlatform/State/ConvertProspectProcessor.php @@ -6,7 +6,10 @@ namespace App\Module\Directory\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; +use App\Module\Directory\Domain\Entity\Address; use App\Module\Directory\Domain\Entity\Client; +use App\Module\Directory\Domain\Entity\CommercialReport; +use App\Module\Directory\Domain\Entity\Contact; use App\Module\Directory\Domain\Entity\Prospect; use App\Module\Directory\Domain\Enum\ProspectStatus; use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface; @@ -14,11 +17,10 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** - * Converts a Prospect into a Client. + * Converts a Prospect into a Client and reassigns its contacts, addresses and + * commercial reports to the new client (preserving the commercial history). * - * Loads the Prospect via the URI id, creates a Client (name = company or name, - * copying contact details), links it back via convertedClient and flags the - * prospect as Won. Idempotent: if already converted, returns it unchanged. + * Idempotent: if already converted, returns it unchanged. * * @implements ProcessorInterface */ @@ -50,6 +52,10 @@ final readonly class ConvertProspectProcessor implements ProcessorInterface $this->entityManager->persist($client); + $this->reassignContacts($prospect, $client); + $this->reassignAddresses($prospect, $client); + $this->reassignReports($prospect, $client); + $prospect->setConvertedClient($client); $prospect->setStatus(ProspectStatus::Won); @@ -57,4 +63,28 @@ final readonly class ConvertProspectProcessor implements ProcessorInterface return $prospect; } + + private function reassignContacts(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(Contact::class)->findBy(['prospect' => $prospect]) as $contact) { + $contact->setClient($client); + $contact->setProspect(null); + } + } + + private function reassignAddresses(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(Address::class)->findBy(['prospect' => $prospect]) as $address) { + $address->setClient($client); + $address->setProspect(null); + } + } + + private function reassignReports(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(CommercialReport::class)->findBy(['prospect' => $prospect]) as $report) { + $report->setClient($client); + $report->setProspect(null); + } + } } diff --git a/src/Module/Directory/Infrastructure/Mcp/Tool/ConvertProspectTool.php b/src/Module/Directory/Infrastructure/Mcp/Tool/ConvertProspectTool.php index b52595b..a049837 100644 --- a/src/Module/Directory/Infrastructure/Mcp/Tool/ConvertProspectTool.php +++ b/src/Module/Directory/Infrastructure/Mcp/Tool/ConvertProspectTool.php @@ -4,7 +4,11 @@ declare(strict_types=1); namespace App\Module\Directory\Infrastructure\Mcp\Tool; +use App\Module\Directory\Domain\Entity\Address; use App\Module\Directory\Domain\Entity\Client; +use App\Module\Directory\Domain\Entity\CommercialReport; +use App\Module\Directory\Domain\Entity\Contact; +use App\Module\Directory\Domain\Entity\Prospect; use App\Module\Directory\Domain\Enum\ProspectStatus; use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface; use App\Shared\Infrastructure\Mcp\Serializer; @@ -44,6 +48,10 @@ class ConvertProspectTool $this->entityManager->persist($client); + $this->reassignContacts($prospect, $client); + $this->reassignAddresses($prospect, $client); + $this->reassignReports($prospect, $client); + $prospect->setConvertedClient($client); $prospect->setStatus(ProspectStatus::Won); @@ -52,4 +60,28 @@ class ConvertProspectTool return json_encode(Serializer::prospect($prospect)); } + + private function reassignContacts(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(Contact::class)->findBy(['prospect' => $prospect]) as $contact) { + $contact->setClient($client); + $contact->setProspect(null); + } + } + + private function reassignAddresses(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(Address::class)->findBy(['prospect' => $prospect]) as $address) { + $address->setClient($client); + $address->setProspect(null); + } + } + + private function reassignReports(Prospect $prospect, Client $client): void + { + foreach ($this->entityManager->getRepository(CommercialReport::class)->findBy(['prospect' => $prospect]) as $report) { + $report->setClient($client); + $report->setProspect(null); + } + } } diff --git a/tests/Module/Directory/ConvertProspectProcessorTest.php b/tests/Module/Directory/ConvertProspectProcessorTest.php new file mode 100644 index 0000000..c232318 --- /dev/null +++ b/tests/Module/Directory/ConvertProspectProcessorTest.php @@ -0,0 +1,67 @@ +get(EntityManagerInterface::class); + + $prospect = new Prospect(); + $prospect->setName('Atelier Test'); + $prospect->setCompany('Atelier Test SARL'); + $em->persist($prospect); + + $contact = new Contact()->setLastName('Durand')->setProspect($prospect); + $address = new Address()->setCity('Niort')->setProspect($prospect); + $report = new CommercialReport() + ->setSubject('Premier contact') + ->setOccurredAt(new DateTimeImmutable('2026-06-01')) + ->setType(ReportType::Call) + ->setProspect($prospect) + ; + $em->persist($contact); + $em->persist($address); + $em->persist($report); + $em->flush(); + + $processor = self::getContainer()->get(ConvertProspectProcessor::class); + $operation = new Post(); + $processor->process($prospect, $operation, ['id' => $prospect->getId()]); + + $em->refresh($contact); + $em->refresh($address); + $em->refresh($report); + + $client = $prospect->getConvertedClient(); + self::assertNotNull($client, 'Prospect should be converted to a client'); + + // Invariants (pas de counts absolus) : chaque sous-entité pointe vers le client, plus vers le prospect. + self::assertSame($client->getId(), $contact->getClient()?->getId()); + self::assertNull($contact->getProspect()); + self::assertSame($client->getId(), $address->getClient()?->getId()); + self::assertNull($address->getProspect()); + self::assertSame($client->getId(), $report->getClient()?->getId()); + self::assertNull($report->getProspect()); + } +}