From 5c3585a1ed22d87949f7a59b23b8342a13d9a1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 16 Apr 2024 14:41:29 +0200 Subject: [PATCH 01/15] Fix loading of environment variable in bootstrap process --- tests/app/config/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/app/config/bootstrap.php b/tests/app/config/bootstrap.php index 4a7385190..6f243bb04 100644 --- a/tests/app/config/bootstrap.php +++ b/tests/app/config/bootstrap.php @@ -23,7 +23,7 @@ if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env (new Dotenv(false))->populate($env); } else { // load all the .env files - (new Dotenv(false))->loadEnv(dirname(__DIR__).'/../../.env.test'); + (new Dotenv(false))->loadEnv(dirname(__DIR__).'/../../.env'); } $_SERVER += $_ENV; From 58325429783421f4e1b4a59a41867b18496d6086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 16 Apr 2024 14:41:39 +0200 Subject: [PATCH 02/15] load also tests for ticket bundle --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 928a65292..482dcc72f 100644 --- a/composer.json +++ b/composer.json @@ -126,8 +126,8 @@ }, "autoload-dev": { "psr-4": { - "App\\": "tests/", "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", + "Chill\\TicketBundle\\Tests": "src/Bundle/ChillTicketBundle/tests", "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests" } From 912fdd63499826f2365317f716f74b693bb29511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 16 Apr 2024 14:41:55 +0200 Subject: [PATCH 03/15] Add phone number search function to PersonACLAwareRepository A new function, findByPhone, has been added to the PersonACLAwareRepository. This function allows searching for people based on their phone numbers. Changes also reflect in the PersonACLAwareRepositoryInterface, and new test cases have been added to the PersonACLAwareRepositoryTest. --- .../Repository/PersonACLAwareRepository.php | 25 +++++++ .../PersonACLAwareRepositoryInterface.php | 10 +++ .../PersonACLAwareRepositoryTest.php | 66 +++++++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 303773c3e..3eaa1d989 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -21,6 +21,8 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\Query; +use libphonenumber\PhoneNumber; +use libphonenumber\PhoneNumberFormat; use Symfony\Component\Security\Core\Security; final readonly class PersonACLAwareRepository implements PersonACLAwareRepositoryInterface @@ -298,4 +300,27 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor \array_map(static fn (Center $c) => $c->getId(), $authorizedCenters) ); } + + public function findByPhone(PhoneNumber $phoneNumber, int $start = 0, int $limit = 20): array + { + $authorizedCenters = $this->authorizationHelper + ->getReachableCenters($this->security->getUser(), PersonVoter::SEE); + + if ([] === $authorizedCenters) { + return []; + } + + $util = \libphonenumber\PhoneNumberUtil::getInstance(); + + return $this->em->createQuery( + 'SELECT p FROM '.Person::class.' p LEFT JOIN p.otherPhoneNumbers opn JOIN p.centerCurrent pcc '. + 'WHERE (p.phonenumber LIKE :phone OR p.mobilenumber LIKE :phone OR opn.phonenumber LIKE :phone) '. + 'AND pcc.center IN (:centers)' + ) + ->setMaxResults($limit) + ->setFirstResult($start) + ->setParameter('phone', $util->format($phoneNumber, PhoneNumberFormat::E164)) + ->setParameter('centers', $authorizedCenters) + ->getResult(); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php index c327ecd40..42e61bf21 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Repository; use Chill\MainBundle\Search\SearchApiQuery; use Chill\PersonBundle\Entity\Person; +use libphonenumber\PhoneNumber; interface PersonACLAwareRepositoryInterface { @@ -60,4 +61,13 @@ interface PersonACLAwareRepositoryInterface ?string $phonenumber = null, ?string $city = null ): array; + + /** + * @return list + */ + public function findByPhone( + PhoneNumber $phoneNumber, + int $start = 0, + int $limit = 20 + ): array; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php index 94df35d88..667242111 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/PersonACLAwareRepositoryTest.php @@ -11,14 +11,17 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Repository; +use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\CountryRepository; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Entity\PersonPhone; use Chill\PersonBundle\Repository\PersonACLAwareRepository; use Chill\PersonBundle\Security\Authorization\PersonVoter; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -98,4 +101,67 @@ final class PersonACLAwareRepositoryTest extends KernelTestCase $this->assertStringContainsString('diallo', strtolower($person->getFirstName().' '.$person->getLastName())); } } + + /** + * @dataProvider providePersonsWithPhoneNumbers + */ + public function testFindByPhonenumber(\libphonenumber\PhoneNumber $phoneNumber, ?int $expectedId): void + { + $user = new User(); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableCenters(Argument::exact($user), Argument::exact(PersonVoter::SEE)) + ->willReturn($this->centerRepository->findAll()); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $repository = new PersonACLAwareRepository( + $security->reveal(), + $this->entityManager, + $this->countryRepository, + $authorizationHelper->reveal() + ); + + $actual = $repository->findByPhone($phoneNumber, 0, 10); + + if (null === $expectedId) { + self::assertCount(0, $actual); + } else { + $actualIds = array_map(fn (Person $person) => $person->getId(), $actual); + + self::assertContains($expectedId, $actualIds); + } + } + + public static function providePersonsWithPhoneNumbers(): iterable + { + self::bootKernel(); + $em = self::getContainer()->get(EntityManagerInterface::class); + $center = $em->createQuery('SELECT c FROM '.Center::class.' c ')->setMaxResults(1) + ->getSingleResult(); + $util = \libphonenumber\PhoneNumberUtil::getInstance(); + + $mobile = $util->parse('+32486123456'); + $fixed = $util->parse('+3281136917'); + $anotherMobile = $util->parse('+32486123478'); + $person = (new Person())->setFirstName('diallo')->setLastName('diallo')->setCenter($center); + $person->setMobilenumber($mobile)->setPhonenumber($fixed); + $otherPhone = new PersonPhone(); + $otherPhone->setPerson($person); + $otherPhone->setPhonenumber($anotherMobile); + $otherPhone->setType('mobile'); + + $em->persist($person); + $em->persist($otherPhone); + + $em->flush(); + + self::ensureKernelShutdown(); + + yield [$mobile, $person->getId()]; + yield [$anotherMobile, $person->getId()]; + yield [$fixed, $person->getId()]; + yield [$util->parse('+331234567890'), null]; + } } From 75fbec5489cb7b97e7975f5b399f1a1307be23e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 17 Apr 2024 09:56:18 +0200 Subject: [PATCH 04/15] Create entities and doctrine mapping for ticket --- composer.json | 2 +- .../ChillMainBundle/Entity/UserGroup.php | 74 ++++++++ .../migrations/Version20240416145021.php | 41 +++++ .../src/Entity/AddresseeHistory.php | 97 ++++++++++ .../ChillTicketBundle/src/Entity/Comment.php | 55 ++++++ .../src/Entity/InputHistory.php | 91 ++++++++++ .../ChillTicketBundle/src/Entity/Motive.php | 55 ++++++ .../src/Entity/MotiveHistory.php | 72 ++++++++ .../src/Entity/PersonHistory.php | 80 +++++++++ .../ChillTicketBundle/src/Entity/Ticket.php | 166 ++++++++++++++++++ .../src/migrations/Version20240416145919.php | 139 +++++++++++++++ 11 files changed, 871 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillMainBundle/Entity/UserGroup.php create mode 100644 src/Bundle/ChillMainBundle/migrations/Version20240416145021.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/Comment.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/InputHistory.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/Motive.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/MotiveHistory.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/PersonHistory.php create mode 100644 src/Bundle/ChillTicketBundle/src/Entity/Ticket.php create mode 100644 src/Bundle/ChillTicketBundle/src/migrations/Version20240416145919.php diff --git a/composer.json b/composer.json index 482dcc72f..1dbb8fc27 100644 --- a/composer.json +++ b/composer.json @@ -127,7 +127,7 @@ "autoload-dev": { "psr-4": { "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", - "Chill\\TicketBundle\\Tests": "src/Bundle/ChillTicketBundle/tests", + "Chill\\TicketBundle\\Tests\\": "src/Bundle/ChillTicketBundle/tests", "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests" } diff --git a/src/Bundle/ChillMainBundle/Entity/UserGroup.php b/src/Bundle/ChillMainBundle/Entity/UserGroup.php new file mode 100644 index 000000000..3bd9870a6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/UserGroup.php @@ -0,0 +1,74 @@ + '[]'])] + private array $label = []; + + /** + * @var \Doctrine\Common\Collections\Collection + */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[ORM\JoinTable(name: 'chill_main_user_group_user')] + private Collection $users; + + public function __construct() + { + $this->users = new ArrayCollection(); + } + + public function addUser(User $user): self + { + if (!$this->users->contains($user)) { + $this->users[] = $user; + } + + return $this; + } + + public function removeUser(User $user): self + { + if ($this->users->contains($user)) { + $this->users->removeElement($user); + } + + return $this; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getLabel(): array + { + return $this->label; + } + + public function getUsers(): Collection + { + return $this->users; + } +} diff --git a/src/Bundle/ChillMainBundle/migrations/Version20240416145021.php b/src/Bundle/ChillMainBundle/migrations/Version20240416145021.php new file mode 100644 index 000000000..f2f8d37dd --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20240416145021.php @@ -0,0 +1,41 @@ +addSql('CREATE SEQUENCE chill_main_user_group_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_user_group (id INT NOT NULL, label JSON DEFAULT \'[]\' NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_main_user_group_user (usergroup_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(usergroup_id, user_id))'); + $this->addSql('CREATE INDEX IDX_1E07F044D2112630 ON chill_main_user_group_user (usergroup_id)'); + $this->addSql('CREATE INDEX IDX_1E07F044A76ED395 ON chill_main_user_group_user (user_id)'); + $this->addSql('ALTER TABLE chill_main_user_group_user ADD CONSTRAINT FK_1E07F044D2112630 FOREIGN KEY (usergroup_id) REFERENCES chill_main_user_group (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_group_user ADD CONSTRAINT FK_1E07F044A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_main_user_group_id_seq'); + $this->addSql('DROP TABLE chill_main_user_group_user'); + $this->addSql('DROP TABLE chill_main_user_group'); + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php b/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php new file mode 100644 index 000000000..3939a24c3 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php @@ -0,0 +1,97 @@ +addresseeUser = $addressee; + } else { + $this->addresseeGroup = $addressee; + } + } + + public function getAddressee(): UserGroup|User + { + if (null !== $this->addresseeGroup) { + return $this->addresseeGroup; + } + + return $this->addresseeUser; + } + + public function getAddresseeGroup(): ?UserGroup + { + return $this->addresseeGroup; + } + + public function getAddresseeUser(): ?User + { + return $this->addresseeUser; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + public function getTicket(): Ticket + { + return $this->ticket; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/Comment.php b/src/Bundle/ChillTicketBundle/src/Entity/Comment.php new file mode 100644 index 000000000..d62e6d8b4 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/Comment.php @@ -0,0 +1,55 @@ + ''])] + private string $content = '' + ) {} + + public function getId(): ?int + { + return $this->id; + } + + public function getContent(): string + { + return $this->content; + } + + public function getTicket(): Ticket + { + return $this->ticket; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/InputHistory.php b/src/Bundle/ChillTicketBundle/src/Entity/InputHistory.php new file mode 100644 index 000000000..2b25ae6ac --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/InputHistory.php @@ -0,0 +1,91 @@ + null])] + private ?\DateTimeImmutable $endDate = null; + + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] + private ?User $removedBy = null; + + public function __construct( + Person|ThirdParty $input, + #[ORM\ManyToOne(targetEntity: Ticket::class)] + #[ORM\JoinColumn(nullable: false)] + private Ticket $ticket, + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false)] + private \DateTimeImmutable $startDate, + ) { + if ($input instanceof Person) { + $this->person = $input; + } else { + $this->thirdParty = $input; + } + } + + public function getId(): ?int + { + return $this->id; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function getRemovedBy(): ?User + { + return $this->removedBy; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + public function getTicket(): Ticket + { + return $this->ticket; + } + + public function getInput(): Person|ThirdParty + { + if (null !== $this->person) { + return $this->person; + } + + return $this->thirdParty; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/Motive.php b/src/Bundle/ChillTicketBundle/src/Entity/Motive.php new file mode 100644 index 000000000..fd744392c --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/Motive.php @@ -0,0 +1,55 @@ + '[]'])] + private array $label = []; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, nullable: false, options: ['default' => true])] + private bool $active = true; + + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): void + { + $this->active = $active; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getLabel(): array + { + return $this->label; + } + + public function setLabel(array $label): void + { + $this->label = $label; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/MotiveHistory.php b/src/Bundle/ChillTicketBundle/src/Entity/MotiveHistory.php new file mode 100644 index 000000000..c96c2d6f4 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/MotiveHistory.php @@ -0,0 +1,72 @@ + null])] + private ?\DateTimeImmutable $endDate = null; + + public function __construct( + #[ORM\ManyToOne(targetEntity: Motive::class)] + #[ORM\JoinColumn(nullable: false)] + private Motive $motive, + #[ORM\ManyToOne(targetEntity: Ticket::class)] + #[ORM\JoinColumn(nullable: false)] + private Ticket $ticket, + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false)] + private \DateTimeImmutable $startDate = new \DateTimeImmutable('now') + ) {} + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getMotive(): Motive + { + return $this->motive; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + public function getTicket(): Ticket + { + return $this->ticket; + } + + public function setEndDate(?\DateTimeImmutable $endDate): void + { + $this->endDate = $endDate; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/PersonHistory.php b/src/Bundle/ChillTicketBundle/src/Entity/PersonHistory.php new file mode 100644 index 000000000..9914f96a1 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/PersonHistory.php @@ -0,0 +1,80 @@ + null])] + private ?\DateTimeImmutable $endDate = null; + + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] + private ?User $removedBy = null; + + public function __construct( + #[ORM\ManyToOne(targetEntity: Person::class, fetch: 'EAGER')] + private Person $person, + #[ORM\ManyToOne(targetEntity: Ticket::class)] + #[ORM\JoinColumn(nullable: false)] + private Ticket $ticket, + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false)] + private \DateTimeImmutable $startDate, + ) { + // keep ticket instance in sync with this + $this->ticket->addPersonHistory($this); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getPerson(): Person + { + return $this->person; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function getTicket(): Ticket + { + return $this->ticket; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + public function getRemovedBy(): ?User + { + return $this->removedBy; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Entity/Ticket.php b/src/Bundle/ChillTicketBundle/src/Entity/Ticket.php new file mode 100644 index 000000000..f74a55a3f --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Entity/Ticket.php @@ -0,0 +1,166 @@ + + */ + #[ORM\OneToMany(targetEntity: AddresseeHistory::class, mappedBy: 'ticket')] + private Collection $addresseeHistory; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'ticket')] + private Collection $comments; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] + private string $externalRef = ''; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: InputHistory::class, mappedBy: 'ticket')] + private Collection $inputHistories; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: MotiveHistory::class, mappedBy: 'ticket')] + private Collection $motiveHistories; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: PersonHistory::class, mappedBy: 'ticket')] + private Collection $personHistories; + + public function __construct() + { + $this->addresseeHistory = new ArrayCollection(); + $this->comments = new ArrayCollection(); + $this->motiveHistories = new ArrayCollection(); + $this->personHistories = new ArrayCollection(); + $this->inputHistories = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getExternalRef(): string + { + return $this->externalRef; + } + + public function setExternalRef(string $externalRef): void + { + $this->externalRef = $externalRef; + } + + /** + * @return list + */ + public function getPersons(): array + { + return $this->personHistories + ->filter(fn (PersonHistory $personHistory) => null === $personHistory->getEndDate()) + ->map(fn (PersonHistory $personHistory) => $personHistory->getPerson()) + ->getValues(); + } + + /** + * Add a PersonHistory. + * + * This method should not be used, use @see{PersonHistory::__construct()} insted. + */ + public function addPersonHistory(PersonHistory $personHistory): void + { + $this->personHistories->add($personHistory); + } + + /** + * @return list + */ + public function getCurrentAddressee(): array + { + $addresses = []; + + foreach ($this->addresseeHistory + ->filter(fn (AddresseeHistory $addresseeHistory) => null === $addresseeHistory->getEndDate()) as $addressHistory) { + $addresses[] = $addressHistory->getAddressee(); + } + + return $addresses; + } + + /** + * @return ReadableCollection + */ + public function getComments(): ReadableCollection + { + return $this->comments; + } + + /** + * @return list + */ + public function getCurrentInputs(): array + { + $inputs = []; + + foreach ($this->inputHistories + ->filter(fn (InputHistory $inputHistory) => null === $inputHistory->getEndDate()) as $inputHistory + ) { + $inputs[] = $inputHistory->getInput(); + } + + return $inputs; + } + + public function getMotive(): ?Motive + { + foreach ($this->motiveHistories as $motiveHistory) { + if (null === $motiveHistory->getEndDate()) { + return $motiveHistory->getMotive(); + } + } + + return null; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/migrations/Version20240416145919.php b/src/Bundle/ChillTicketBundle/src/migrations/Version20240416145919.php new file mode 100644 index 000000000..f627a4143 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/migrations/Version20240416145919.php @@ -0,0 +1,139 @@ +addSql('CREATE SCHEMA chill_ticket'); + $this->addSql('CREATE SEQUENCE chill_ticket.addressee_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_ticket.comment_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_ticket.input_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_ticket.motive_id_seq INCREMENT BY 1 MINVALUE 1 START 1000'); + $this->addSql('CREATE SEQUENCE chill_ticket.motives_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_ticket.person_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_ticket.ticket_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_ticket.addressee_history (id INT NOT NULL, ticket_id INT NOT NULL, startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, addresseeUser_id INT DEFAULT NULL, addresseeGroup_id INT DEFAULT NULL, createdBy_id INT DEFAULT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_434EBDBD4D06F00C ON chill_ticket.addressee_history (addresseeUser_id)'); + $this->addSql('CREATE INDEX IDX_434EBDBD776D9A84 ON chill_ticket.addressee_history (addresseeGroup_id)'); + $this->addSql('CREATE INDEX IDX_434EBDBD700047D2 ON chill_ticket.addressee_history (ticket_id)'); + $this->addSql('CREATE INDEX IDX_434EBDBD3174800F ON chill_ticket.addressee_history (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_434EBDBD65FF1AEC ON chill_ticket.addressee_history (updatedBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.addressee_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.addressee_history.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.addressee_history.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE TABLE chill_ticket.comment (id INT NOT NULL, ticket_id INT NOT NULL, content TEXT DEFAULT \'\' NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, createdBy_id INT DEFAULT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_79EBD416700047D2 ON chill_ticket.comment (ticket_id)'); + $this->addSql('CREATE INDEX IDX_79EBD4163174800F ON chill_ticket.comment (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_79EBD41665FF1AEC ON chill_ticket.comment (updatedBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.comment.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.comment.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE TABLE chill_ticket.input_history (id INT NOT NULL, person_id INT DEFAULT NULL, ticket_id INT NOT NULL, endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, thirdParty_id INT DEFAULT NULL, removedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_E2AA301F217BBB47 ON chill_ticket.input_history (person_id)'); + $this->addSql('CREATE INDEX IDX_E2AA301F3EA5CAB0 ON chill_ticket.input_history (thirdParty_id)'); + $this->addSql('CREATE INDEX IDX_E2AA301FB8346CCF ON chill_ticket.input_history (removedBy_id)'); + $this->addSql('CREATE INDEX IDX_E2AA301F700047D2 ON chill_ticket.input_history (ticket_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.input_history.endDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.input_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE TABLE chill_ticket.motive (id INT NOT NULL, label JSON DEFAULT \'[]\' NOT NULL, active BOOLEAN DEFAULT true NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_ticket.motives_history (id INT NOT NULL, motive_id INT NOT NULL, ticket_id INT NOT NULL, endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, createdBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_48995CFF9658649C ON chill_ticket.motives_history (motive_id)'); + $this->addSql('CREATE INDEX IDX_48995CFF700047D2 ON chill_ticket.motives_history (ticket_id)'); + $this->addSql('CREATE INDEX IDX_48995CFF3174800F ON chill_ticket.motives_history (createdBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.motives_history.endDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.motives_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.motives_history.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE TABLE chill_ticket.person_history (id INT NOT NULL, person_id INT DEFAULT NULL, ticket_id INT NOT NULL, endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, removedBy_id INT DEFAULT NULL, createdBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_F2969246B8346CCF ON chill_ticket.person_history (removedBy_id)'); + $this->addSql('CREATE INDEX IDX_F2969246217BBB47 ON chill_ticket.person_history (person_id)'); + $this->addSql('CREATE INDEX IDX_F2969246700047D2 ON chill_ticket.person_history (ticket_id)'); + $this->addSql('CREATE INDEX IDX_F29692463174800F ON chill_ticket.person_history (createdBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.person_history.endDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.person_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.person_history.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE TABLE chill_ticket.ticket (id INT NOT NULL, externalRef TEXT DEFAULT \'\' NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, createdBy_id INT DEFAULT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_B0A5F7233174800F ON chill_ticket.ticket (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_B0A5F72365FF1AEC ON chill_ticket.ticket (updatedBy_id)'); + $this->addSql('COMMENT ON COLUMN chill_ticket.ticket.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_ticket.ticket.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_ticket.addressee_history ADD CONSTRAINT FK_434EBDBD4D06F00C FOREIGN KEY (addresseeUser_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history ADD CONSTRAINT FK_434EBDBD776D9A84 FOREIGN KEY (addresseeGroup_id) REFERENCES chill_main_user_group (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history ADD CONSTRAINT FK_434EBDBD700047D2 FOREIGN KEY (ticket_id) REFERENCES chill_ticket.ticket (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history ADD CONSTRAINT FK_434EBDBD3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history ADD CONSTRAINT FK_434EBDBD65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.comment ADD CONSTRAINT FK_79EBD416700047D2 FOREIGN KEY (ticket_id) REFERENCES chill_ticket.ticket (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.comment ADD CONSTRAINT FK_79EBD4163174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.comment ADD CONSTRAINT FK_79EBD41665FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.input_history ADD CONSTRAINT FK_E2AA301F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.input_history ADD CONSTRAINT FK_E2AA301F3EA5CAB0 FOREIGN KEY (thirdParty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.input_history ADD CONSTRAINT FK_E2AA301FB8346CCF FOREIGN KEY (removedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.input_history ADD CONSTRAINT FK_E2AA301F700047D2 FOREIGN KEY (ticket_id) REFERENCES chill_ticket.ticket (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.motives_history ADD CONSTRAINT FK_48995CFF9658649C FOREIGN KEY (motive_id) REFERENCES chill_ticket.motive (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.motives_history ADD CONSTRAINT FK_48995CFF700047D2 FOREIGN KEY (ticket_id) REFERENCES chill_ticket.ticket (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.motives_history ADD CONSTRAINT FK_48995CFF3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.person_history ADD CONSTRAINT FK_F2969246B8346CCF FOREIGN KEY (removedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.person_history ADD CONSTRAINT FK_F2969246217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.person_history ADD CONSTRAINT FK_F2969246700047D2 FOREIGN KEY (ticket_id) REFERENCES chill_ticket.ticket (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.person_history ADD CONSTRAINT FK_F29692463174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.ticket ADD CONSTRAINT FK_B0A5F7233174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_ticket.ticket ADD CONSTRAINT FK_B0A5F72365FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_ticket.addressee_history_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.comment_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.input_history_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.motive_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.motives_history_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.person_history_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_ticket.ticket_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history DROP CONSTRAINT FK_434EBDBD4D06F00C'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history DROP CONSTRAINT FK_434EBDBD776D9A84'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history DROP CONSTRAINT FK_434EBDBD700047D2'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history DROP CONSTRAINT FK_434EBDBD3174800F'); + $this->addSql('ALTER TABLE chill_ticket.addressee_history DROP CONSTRAINT FK_434EBDBD65FF1AEC'); + $this->addSql('ALTER TABLE chill_ticket.comment DROP CONSTRAINT FK_79EBD416700047D2'); + $this->addSql('ALTER TABLE chill_ticket.comment DROP CONSTRAINT FK_79EBD4163174800F'); + $this->addSql('ALTER TABLE chill_ticket.comment DROP CONSTRAINT FK_79EBD41665FF1AEC'); + $this->addSql('ALTER TABLE chill_ticket.input_history DROP CONSTRAINT FK_E2AA301F217BBB47'); + $this->addSql('ALTER TABLE chill_ticket.input_history DROP CONSTRAINT FK_E2AA301F3EA5CAB0'); + $this->addSql('ALTER TABLE chill_ticket.input_history DROP CONSTRAINT FK_E2AA301FB8346CCF'); + $this->addSql('ALTER TABLE chill_ticket.input_history DROP CONSTRAINT FK_E2AA301F700047D2'); + $this->addSql('ALTER TABLE chill_ticket.motives_history DROP CONSTRAINT FK_48995CFF9658649C'); + $this->addSql('ALTER TABLE chill_ticket.motives_history DROP CONSTRAINT FK_48995CFF700047D2'); + $this->addSql('ALTER TABLE chill_ticket.motives_history DROP CONSTRAINT FK_48995CFF3174800F'); + $this->addSql('ALTER TABLE chill_ticket.person_history DROP CONSTRAINT FK_F2969246B8346CCF'); + $this->addSql('ALTER TABLE chill_ticket.person_history DROP CONSTRAINT FK_F2969246217BBB47'); + $this->addSql('ALTER TABLE chill_ticket.person_history DROP CONSTRAINT FK_F2969246700047D2'); + $this->addSql('ALTER TABLE chill_ticket.person_history DROP CONSTRAINT FK_F29692463174800F'); + $this->addSql('ALTER TABLE chill_ticket.ticket DROP CONSTRAINT FK_B0A5F7233174800F'); + $this->addSql('ALTER TABLE chill_ticket.ticket DROP CONSTRAINT FK_B0A5F72365FF1AEC'); + $this->addSql('DROP TABLE chill_ticket.addressee_history'); + $this->addSql('DROP TABLE chill_ticket.comment'); + $this->addSql('DROP TABLE chill_ticket.input_history'); + $this->addSql('DROP TABLE chill_ticket.motive'); + $this->addSql('DROP TABLE chill_ticket.motives_history'); + $this->addSql('DROP TABLE chill_ticket.person_history'); + $this->addSql('DROP TABLE chill_ticket.ticket'); + $this->addSql('DROP SCHEMA chill_ticket CASCADE'); + } +} From 4b30d922820bd47739c461f9514478440d948e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 17 Apr 2024 09:56:41 +0200 Subject: [PATCH 05/15] Add ticket creation and associating by phone number functionality This update introduces new features allowing the creation of tickets and associating them with a phone number. Specifically, relevant commands and their handlers have been created along with corresponding tests. An endpoint for ticket creation has also been set up, and the ViewTicketController has been renamed and refactored to EditTicketController to better reflect its function. --- .../Ticket/AssociateByPhonenumberCommand.php | 19 ++++++ .../Command/Ticket/CreateTicketCommand.php | 19 ++++++ .../AssociateByPhonenumberCommandHandler.php | 41 ++++++++++++ .../Handler/CreateTicketCommandHandler.php | 26 ++++++++ .../src/Controller/CreateTicketController.php | 60 ++++++++++++++++++ ...ontroller.php => EditTicketController.php} | 10 +-- .../src/config/services.yaml | 3 +- ...sociateByPhonenumberCommandHandlerTest.php | 62 +++++++++++++++++++ .../CreateTicketCommandHandlerTest.php | 48 ++++++++++++++ 9 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 src/Bundle/ChillTicketBundle/src/Command/Ticket/AssociateByPhonenumberCommand.php create mode 100644 src/Bundle/ChillTicketBundle/src/Command/Ticket/CreateTicketCommand.php create mode 100644 src/Bundle/ChillTicketBundle/src/Command/Ticket/Handler/AssociateByPhonenumberCommandHandler.php create mode 100644 src/Bundle/ChillTicketBundle/src/Command/Ticket/Handler/CreateTicketCommandHandler.php create mode 100644 src/Bundle/ChillTicketBundle/src/Controller/CreateTicketController.php rename src/Bundle/ChillTicketBundle/src/Controller/{ViewTicketController.php => EditTicketController.php} (64%) create mode 100644 src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/AssociateByPhonenumberCommandHandlerTest.php create mode 100644 src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/CreateTicketCommandHandlerTest.php diff --git a/src/Bundle/ChillTicketBundle/src/Command/Ticket/AssociateByPhonenumberCommand.php b/src/Bundle/ChillTicketBundle/src/Command/Ticket/AssociateByPhonenumberCommand.php new file mode 100644 index 000000000..61e652190 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Command/Ticket/AssociateByPhonenumberCommand.php @@ -0,0 +1,19 @@ +phoneNumberUtil->parse($command->phonenumber); + $persons = $this->personRepository->findByPhone($phone); + + foreach ($persons as $person) { + $history = new PersonHistory($person, $ticket, $this->clock->now()); + $this->entityManager->persist($history); + } + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Command/Ticket/Handler/CreateTicketCommandHandler.php b/src/Bundle/ChillTicketBundle/src/Command/Ticket/Handler/CreateTicketCommandHandler.php new file mode 100644 index 000000000..a62c0418e --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Command/Ticket/Handler/CreateTicketCommandHandler.php @@ -0,0 +1,26 @@ +setExternalRef($command->externalReference); + + return $ticket; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Controller/CreateTicketController.php b/src/Bundle/ChillTicketBundle/src/Controller/CreateTicketController.php new file mode 100644 index 000000000..ec2ea7b90 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Controller/CreateTicketController.php @@ -0,0 +1,60 @@ +security->isGranted('ROLE_USER')) { + throw new AccessDeniedHttpException('Only users are allowed to create tickets.'); + } + + $createCommand = new CreateTicketCommand($request->query->get('extId', '')); + $ticket = $this->createTicketCommandHandler->__invoke($createCommand); + + $this->entityManager->persist($ticket); + + if ($request->query->has('caller')) { + $associateByPhonenumberCommand = new AssociateByPhonenumberCommand($request->query->get('caller')); + $this->associateByPhonenumberCommandHandler->__invoke($ticket, $associateByPhonenumberCommand); + } + + $this->entityManager->flush(); + + return new RedirectResponse( + $this->urlGenerator->generate('chill_ticket_ticket_edit', ['id' => $ticket->getId()]) + ); + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Controller/ViewTicketController.php b/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php similarity index 64% rename from src/Bundle/ChillTicketBundle/src/Controller/ViewTicketController.php rename to src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php index 9b35c0d48..a51c3a4a8 100644 --- a/src/Bundle/ChillTicketBundle/src/Controller/ViewTicketController.php +++ b/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php @@ -11,14 +11,16 @@ declare(strict_types=1); namespace Chill\TicketBundle\Controller; +use Chill\TicketBundle\Entity\Ticket; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -class ViewTicketController +class EditTicketController { - #[Route('/{_locale}/ticket/ticket/{ticketId}', name: 'chill_ticket_ticket_view')] - public function __invoke(int $ticketId): Response - { + #[Route('/{_locale}/ticket/ticket/{id}/edit', name: 'chill_ticket_ticket_edit')] + public function __invoke( + Ticket $ticket + ): Response { return new Response('ok'); } } diff --git a/src/Bundle/ChillTicketBundle/src/config/services.yaml b/src/Bundle/ChillTicketBundle/src/config/services.yaml index 6d2f9e1bf..372baa81f 100644 --- a/src/Bundle/ChillTicketBundle/src/config/services.yaml +++ b/src/Bundle/ChillTicketBundle/src/config/services.yaml @@ -8,5 +8,6 @@ services: tags: - controller.service_arguments - + Chill\TicketBundle\Command\Ticket\Handler\: + resource: '../Command/Ticket/Handler/' diff --git a/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/AssociateByPhonenumberCommandHandlerTest.php b/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/AssociateByPhonenumberCommandHandlerTest.php new file mode 100644 index 000000000..ab0744015 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/AssociateByPhonenumberCommandHandlerTest.php @@ -0,0 +1,62 @@ +prophesize(ObjectManager::class); + + return new AssociateByPhonenumberCommandHandler( + $personACLAwareRepository, + PhoneNumberUtil::getInstance(), + new MockClock(), + $objectManager->reveal() + ); + } + + public function testHandleWithPersonFoundByPhonenumber(): void + { + $person = new Person(); + + $personAclAwareRepository = $this->prophesize(PersonACLAwareRepositoryInterface::class); + $personAclAwareRepository->findByPhone(Argument::any())->willReturn([$person]); + + $handler = $this->getHandler($personAclAwareRepository->reveal()); + + $ticket = new Ticket(); + $handler($ticket, new AssociateByPhonenumberCommand('+3281136917')); + + self::assertSame($person, $ticket->getPersons()[0]); + } +} diff --git a/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/CreateTicketCommandHandlerTest.php b/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/CreateTicketCommandHandlerTest.php new file mode 100644 index 000000000..3b94dd706 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Command/Ticket/Handler/CreateTicketCommandHandlerTest.php @@ -0,0 +1,48 @@ +getHandler())($command); + + self::assertInstanceOf(Ticket::class, $actual); + self::assertEquals('', $actual->getExternalRef()); + } + + public function testHandleWithReference(): void + { + $command = new CreateTicketCommand($ref = 'external-ref'); + $actual = ($this->getHandler())($command); + + self::assertInstanceOf(Ticket::class, $actual); + self::assertEquals($ref, $actual->getExternalRef()); + } +} From 36bc4dab24ae952c5994e32ebe9696df7a2bf7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 17 Apr 2024 10:26:33 +0200 Subject: [PATCH 06/15] Configure a testsuite for TicketBundle --- phpunit.xml.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 336877a0c..fa8f479c5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -49,6 +49,10 @@ src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php + + + src/Bundle/ChillTicketBundle/tests/ +