From 2f930ac138f406ca265dc6ea16e229742b37e224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 19 Nov 2025 14:45:01 +0000 Subject: [PATCH] Add filtering tickets by person center --- .../ChillTicketBundle/chill.api.specs.yaml | 26 ++ .../CenterForTicketListApiController.php | 52 ++++ .../Controller/TicketListApiController.php | 17 ++ .../Repository/TicketACLAwareRepository.php | 30 +++ .../TicketACLAwareRepositoryInterface.php | 3 +- ...tListApiControllerByAddresseeGroupTest.php | 4 + ...TicketListApiControllerByAddresseeTest.php | 13 +- ...etListApiControllerByAddresseeToMeTest.php | 4 +- ...ketListApiControllerByCreatedAfterTest.php | 11 +- ...etListApiControllerByCreatedBeforeTest.php | 11 +- .../TicketListApiControllerByCreatorTest.php | 10 +- ...ketListApiControllerByPersonCenterTest.php | 240 ++++++++++++++++++ ...piControllerByResponseTimeExceededTest.php | 7 +- .../TicketListApiControllerByTicketIdTest.php | 7 +- ...ApiControllerCurrentStateEmergencyTest.php | 7 +- ...icketListApiControllerCurrentStateTest.php | 7 +- .../TicketListApiControllerMotivesTest.php | 14 +- .../TicketListApiControllerTest.php | 13 +- .../TicketACLAwareRepositoryTest.php | 16 ++ 19 files changed, 461 insertions(+), 31 deletions(-) create mode 100644 src/Bundle/ChillTicketBundle/src/Controller/CenterForTicketListApiController.php create mode 100644 src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByPersonCenterTest.php diff --git a/src/Bundle/ChillTicketBundle/chill.api.specs.yaml b/src/Bundle/ChillTicketBundle/chill.api.specs.yaml index f0255fb19..b1bdc4269 100644 --- a/src/Bundle/ChillTicketBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillTicketBundle/chill.api.specs.yaml @@ -54,6 +54,20 @@ paths: responses: 200: description: "OK" + /1.0/ticket/search/authorized-centers: + get: + tags: + - ticket + summary: List of centers authorized for the current user + responses: + 200: + description: "OK" + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Center' /1.0/ticket/ticket/list: get: tags: @@ -190,6 +204,18 @@ paths: type: integer format: integer minimum: 1 + - name: byPersonCenter + in: query + description: The id of the centers. The list of centers can be search through /api/1.0/ticket/search/authorized-centers endpoint. + required: false + style: form + explode: false + schema: + type: array + items: + type: integer + format: integer + minimum: 1 responses: 200: description: OK diff --git a/src/Bundle/ChillTicketBundle/src/Controller/CenterForTicketListApiController.php b/src/Bundle/ChillTicketBundle/src/Controller/CenterForTicketListApiController.php new file mode 100644 index 000000000..11b2ac961 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Controller/CenterForTicketListApiController.php @@ -0,0 +1,52 @@ +security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException(); + } + + $centers = $this->authorizationHelperForCurrentUser->getReachableCenters(PersonVoter::SEE); + + return new JsonResponse( + $this->serializer->serialize($centers, 'json', ['groups' => 'read']), + Response::HTTP_OK, + json: true + ); + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Controller/TicketListApiController.php b/src/Bundle/ChillTicketBundle/src/Controller/TicketListApiController.php index fd1db6e22..1a4e5ccdb 100644 --- a/src/Bundle/ChillTicketBundle/src/Controller/TicketListApiController.php +++ b/src/Bundle/ChillTicketBundle/src/Controller/TicketListApiController.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\TicketBundle\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -46,6 +47,7 @@ final readonly class TicketListApiController ParameterBagInterface $parameterBag, private UserRepositoryInterface $userRepository, private UserGroupRepositoryInterface $userGroupRepository, + private CenterRepositoryInterface $centerRepository, ) { $this->expectedTimeResponseDelay = new \DateInterval($parameterBag->get('chill_ticket')['ticket']['response_time_exceeded_delay']); } @@ -191,6 +193,21 @@ final readonly class TicketListApiController } } + if ($request->query->has('byPersonCenter')) { + $centerIds = explode(',', $request->query->get('byPersonCenter')); + foreach ($centerIds as $id) { + if (!is_numeric($id) || 0 === ((int) $id)) { + throw new BadRequestHttpException('Only numbers are allowed in by center parameter'); + } + + $center = $this->centerRepository->find($id); + if (null === $center) { + throw new BadRequestHttpException('Center not found'); + } + $params['byPersonCenter'][] = $center; + } + } + $nb = $this->ticketRepository->countTickets($params); $paginator = $this->paginatorFactory->create($nb); diff --git a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php index ad8fa1387..442fc077e 100644 --- a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php +++ b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\TicketBundle\Repository; +use Chill\PersonBundle\Entity\Person\PersonCenterHistory; use Chill\TicketBundle\Entity\AddresseeHistory; use Chill\TicketBundle\Entity\EmergencyStatusHistory; use Chill\TicketBundle\Entity\MotiveHistory; @@ -203,6 +204,35 @@ final readonly class TicketACLAwareRepository implements TicketACLAwareRepositor $qb->andWhere($addresseeGroupOr); } + if (array_key_exists('byPersonCenter', $params)) { + $orx = $qb->expr()->orX(); + foreach ($params['byPersonCenter'] as $userCenter) { + $orx->add( + $qb->expr()->exists(sprintf( + 'SELECT 1 FROM %s ticket_person_%d + JOIN %s person_center_%d WITH person_center_%d.person = ticket_person_%d.person AND TRUE = OVERLAPSI(ticket_person_%d.startDate, ticket_person_%d.startDate),(person_center_%d.startDate, person_center_%d.endDate) + WHERE ticket_person_%d.ticket = t AND ticket_person_%d.endDate IS NULL AND person_center_%d.center = :center_%d', + PersonHistory::class, + ++$i, + PersonCenterHistory::class, + $i, + $i, + $i, + $i, + $i, + $i, + $i, + $i, + $i, + $i, + $i, + )) + ); + $qb->setParameter(sprintf('center_%d', $i), $userCenter); + } + $qb->andWhere($orx); + } + return $qb; } } diff --git a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php index 646ca3403..1887e7ffd 100644 --- a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\TicketBundle\Repository; +use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserGroup; use Chill\PersonBundle\Entity\Person; @@ -22,7 +23,7 @@ use Chill\TicketBundle\Entity\Ticket; /** * Repository to find tickets, taking care of permissions. * - * @phpstan-type TicketACLAwareRepositoryParam array{byPerson?: list, byCurrentState?: list, byCurrentStateEmergency?: list, byMotives?: list, byCreatedBefore?: \DateTimeImmutable, byCreatedAfter?: \DateTimeImmutable, byAddressee?: list, byAddresseeGroup?: list, byCreator?: list, byTicketId?: int} + * @phpstan-type TicketACLAwareRepositoryParam array{byPerson?: list, byCurrentState?: list, byCurrentStateEmergency?: list, byMotives?: list, byCreatedBefore?: \DateTimeImmutable, byCreatedAfter?: \DateTimeImmutable, byAddressee?: list, byAddresseeGroup?: list, byCreator?: list, byTicketId?: int, byPersonCenter?: list
} */ interface TicketACLAwareRepositoryInterface { diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeGroupTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeGroupTest.php index 94c1bf705..afbe251d9 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeGroupTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeGroupTest.php @@ -14,6 +14,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Entity\UserGroup; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -93,6 +94,7 @@ final class TicketListApiControllerByAddresseeGroupTest extends TestCase new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), $groupRepository->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal(), ); $request = new Request(query: ['byAddresseeGroup' => '10']); @@ -159,6 +161,7 @@ final class TicketListApiControllerByAddresseeGroupTest extends TestCase new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), $groupRepository->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal(), ); $request = new Request(query: ['byAddresseeGroup' => '10,20']); @@ -201,6 +204,7 @@ final class TicketListApiControllerByAddresseeGroupTest extends TestCase new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), $groupRepository->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal(), ); $request = new Request(query: ['byAddresseeGroup' => '10,20']); diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeTest.php index 3a4099fae..62fdcb278 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeTest.php @@ -14,6 +14,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -94,7 +95,8 @@ final class TicketListApiControllerByAddresseeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byAddressee filter @@ -168,7 +170,8 @@ final class TicketListApiControllerByAddresseeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with multiple byAddressee filter @@ -216,7 +219,8 @@ final class TicketListApiControllerByAddresseeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byAddressee filter with non-existent user @@ -286,7 +290,8 @@ final class TicketListApiControllerByAddresseeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with both byAddressee and byAddresseeToMe filters diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeToMeTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeToMeTest.php index ebc984e7e..c0054bd90 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeToMeTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByAddresseeToMeTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; @@ -92,7 +93,8 @@ final class TicketListApiControllerByAddresseeToMeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byAddresseeToMe filter diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedAfterTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedAfterTest.php index c11de568d..3efd0bb8e 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedAfterTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedAfterTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -99,7 +100,8 @@ final class TicketListApiControllerByCreatedAfterTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byCreatedAfter filter in RFC3339 format @@ -173,7 +175,8 @@ final class TicketListApiControllerByCreatedAfterTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byCreatedAfter filter in RFC3339_EXTENDED format @@ -204,6 +207,7 @@ final class TicketListApiControllerByCreatedAfterTest extends TestCase $personRepository = $this->prophesize(PersonRepository::class); $motiveRepository = $this->prophesize(MotiveRepository::class); $userRepository = $this->prophesize(UserRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); // Create controller $controller = new TicketListApiController( @@ -216,7 +220,8 @@ final class TicketListApiControllerByCreatedAfterTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), ); // Create request with byCreatedAfter filter in invalid format diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedBeforeTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedBeforeTest.php index da0f16e47..e02471866 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedBeforeTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatedBeforeTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -99,7 +100,8 @@ final class TicketListApiControllerByCreatedBeforeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byCreatedAfter filter in RFC3339 format @@ -173,7 +175,8 @@ final class TicketListApiControllerByCreatedBeforeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byCreatedAfter filter in RFC3339_EXTENDED format @@ -204,6 +207,7 @@ final class TicketListApiControllerByCreatedBeforeTest extends TestCase $personRepository = $this->prophesize(PersonRepository::class); $motiveRepository = $this->prophesize(MotiveRepository::class); $userRepository = $this->prophesize(UserRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); // Create controller $controller = new TicketListApiController( @@ -216,7 +220,8 @@ final class TicketListApiControllerByCreatedBeforeTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), ); // Create request with byCreatedAfter filter in invalid format diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatorTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatorTest.php index a8828f545..513e14014 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatorTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByCreatorTest.php @@ -14,6 +14,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -90,7 +91,8 @@ final class TicketListApiControllerByCreatorTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); $request = new Request(query: ['byCreator' => '1']); @@ -151,7 +153,8 @@ final class TicketListApiControllerByCreatorTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); $request = new Request(query: ['byCreator' => '1,2']); @@ -194,7 +197,8 @@ final class TicketListApiControllerByCreatorTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); $request = new Request(query: ['byCreator' => '99']); diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByPersonCenterTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByPersonCenterTest.php new file mode 100644 index 000000000..a141029ba --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByPersonCenterTest.php @@ -0,0 +1,240 @@ +prophesize(Security::class); + $security->isGranted('ROLE_USER')->willReturn(true); + + $center = new Center(); + + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $centerRepository->find(10)->willReturn($center); + + $ticketRepository = $this->prophesize(TicketACLAwareRepositoryInterface::class); + $tickets = [new Ticket(), new Ticket()]; + $ticketRepository->countTickets( + Argument::that(fn ($params) => isset($params['byPersonCenter']) && in_array($center, $params['byPersonCenter'], true)) + )->shouldBeCalled()->willReturn(2); + $ticketRepository->findTickets( + Argument::that(fn ($params) => isset($params['byPersonCenter']) && in_array($center, $params['byPersonCenter'], true)), + 0, + 10 + )->shouldBeCalled()->willReturn($tickets); + + $paginator = $this->prophesize(PaginatorInterface::class); + $paginator->getCurrentPageFirstItemNumber()->willReturn(0); + $paginator->getItemsPerPage()->willReturn(10); + + $paginatorFactory = $this->prophesize(PaginatorFactoryInterface::class); + $paginatorFactory->create(2)->willReturn($paginator->reveal()); + + $serializer = $this->prophesize(SerializerInterface::class); + $serializer->serialize( + Argument::that(fn (Collection $collection) => $collection->getItems() === $tickets), + 'json', + ['groups' => 'read:simple'] + )->willReturn('{"items":[{},{}],"pagination":{}}'); + + $personRepository = $this->prophesize(PersonRepository::class); + $motiveRepository = $this->prophesize(MotiveRepository::class); + $userRepository = $this->prophesize(UserRepositoryInterface::class); + + $controller = new TicketListApiController( + $security->reveal(), + $ticketRepository->reveal(), + $paginatorFactory->reveal(), + $serializer->reveal(), + $personRepository->reveal(), + $motiveRepository->reveal(), + new MockClock(), + new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), + $userRepository->reveal(), + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), + ); + + $request = new Request(query: ['byPersonCenter' => '10']); + + $response = $controller->listTicket($request); + + self::assertInstanceOf(JsonResponse::class, $response); + self::assertSame('{"items":[{},{}],"pagination":{}}', $response->getContent()); + } + + public function testListTicketWithMultipleCenters(): void + { + $security = $this->prophesize(Security::class); + $security->isGranted('ROLE_USER')->willReturn(true); + + $center1 = new Center(); + $center2 = new Center(); + + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $centerRepository->find(10)->willReturn($center1); + $centerRepository->find(20)->willReturn($center2); + + $ticketRepository = $this->prophesize(TicketACLAwareRepositoryInterface::class); + $tickets = [new Ticket(), new Ticket()]; + $ticketRepository->countTickets( + Argument::that(fn ($params) => isset($params['byPersonCenter']) && in_array($center1, $params['byPersonCenter'], true) && in_array($center2, $params['byPersonCenter'], true)) + )->willReturn(2); + $ticketRepository->findTickets( + Argument::that(fn ($params) => isset($params['byPersonCenter']) && in_array($center1, $params['byPersonCenter'], true) && in_array($center2, $params['byPersonCenter'], true)), + 0, + 10 + )->willReturn($tickets); + + $paginator = $this->prophesize(PaginatorInterface::class); + $paginator->getCurrentPageFirstItemNumber()->willReturn(0); + $paginator->getItemsPerPage()->willReturn(10); + + $paginatorFactory = $this->prophesize(PaginatorFactoryInterface::class); + $paginatorFactory->create(2)->willReturn($paginator->reveal()); + + $serializer = $this->prophesize(SerializerInterface::class); + $serializer->serialize( + Argument::that(fn (Collection $collection) => $collection->getItems() === $tickets), + 'json', + ['groups' => 'read:simple'] + )->willReturn('{"items":[{},{}],"pagination":{}}'); + + $personRepository = $this->prophesize(PersonRepository::class); + $motiveRepository = $this->prophesize(MotiveRepository::class); + $userRepository = $this->prophesize(UserRepositoryInterface::class); + + $controller = new TicketListApiController( + $security->reveal(), + $ticketRepository->reveal(), + $paginatorFactory->reveal(), + $serializer->reveal(), + $personRepository->reveal(), + $motiveRepository->reveal(), + new MockClock(), + new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), + $userRepository->reveal(), + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), + ); + + $request = new Request(query: ['byPersonCenter' => '10,20']); + + $response = $controller->listTicket($request); + + self::assertInstanceOf(JsonResponse::class, $response); + self::assertSame('{"items":[{},{}],"pagination":{}}', $response->getContent()); + } + + public function testListTicketWithNonNumericCenterId(): void + { + self::expectException(BadRequestHttpException::class); + self::expectExceptionMessage('Only numbers are allowed in by center parameter'); + + $security = $this->prophesize(Security::class); + $security->isGranted('ROLE_USER')->willReturn(true); + + $ticketRepository = $this->prophesize(TicketACLAwareRepositoryInterface::class); + $paginatorFactory = $this->prophesize(PaginatorFactoryInterface::class); + $serializer = $this->prophesize(SerializerInterface::class); + $personRepository = $this->prophesize(PersonRepository::class); + $motiveRepository = $this->prophesize(MotiveRepository::class); + $userRepository = $this->prophesize(UserRepositoryInterface::class); + $userGroupRepository = $this->prophesize(UserGroupRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + + $controller = new TicketListApiController( + $security->reveal(), + $ticketRepository->reveal(), + $paginatorFactory->reveal(), + $serializer->reveal(), + $personRepository->reveal(), + $motiveRepository->reveal(), + new MockClock(), + new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), + $userRepository->reveal(), + $userGroupRepository->reveal(), + $centerRepository->reveal(), + ); + + $request = new Request(query: ['byPersonCenter' => 'foo']); + $controller->listTicket($request); + } + + public function testListTicketWithCenterNotFound(): void + { + self::expectException(BadRequestHttpException::class); + self::expectExceptionMessage('Center not found'); + + $security = $this->prophesize(Security::class); + $security->isGranted('ROLE_USER')->willReturn(true); + + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); + $centerRepository->find(10)->willReturn(null); + + $ticketRepository = $this->prophesize(TicketACLAwareRepositoryInterface::class); + $paginatorFactory = $this->prophesize(PaginatorFactoryInterface::class); + $serializer = $this->prophesize(SerializerInterface::class); + $personRepository = $this->prophesize(PersonRepository::class); + $motiveRepository = $this->prophesize(MotiveRepository::class); + $userRepository = $this->prophesize(UserRepositoryInterface::class); + + $controller = new TicketListApiController( + $security->reveal(), + $ticketRepository->reveal(), + $paginatorFactory->reveal(), + $serializer->reveal(), + $personRepository->reveal(), + $motiveRepository->reveal(), + new MockClock(), + new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), + $userRepository->reveal(), + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), + ); + + $request = new Request(query: ['byPersonCenter' => '10']); + $controller->listTicket($request); + } +} diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByResponseTimeExceededTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByResponseTimeExceededTest.php index 54fae993b..17241547e 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByResponseTimeExceededTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByResponseTimeExceededTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -109,7 +110,8 @@ final class TicketListApiControllerByResponseTimeExceededTest extends TestCase $mockClock, new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byResponseTimeExceeded parameter only @@ -194,7 +196,8 @@ final class TicketListApiControllerByResponseTimeExceededTest extends TestCase $mockClock, new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with both byCreatedAfter and byResponseTimeExceeded parameters diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByTicketIdTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByTicketIdTest.php index f3fb1c1eb..1bc10e078 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByTicketIdTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerByTicketIdTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -92,7 +93,8 @@ final class TicketListApiControllerByTicketIdTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $userGroupRepository->reveal() + $userGroupRepository->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with byTicketId filter @@ -135,7 +137,8 @@ final class TicketListApiControllerByTicketIdTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $userGroupRepository->reveal() + $userGroupRepository->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Use -1 to trigger the controller's validation error diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateEmergencyTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateEmergencyTest.php index ea4636ffe..cee3b6119 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateEmergencyTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateEmergencyTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -89,7 +90,8 @@ final class TicketListApiControllerCurrentStateEmergencyTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with emergency filter @@ -131,7 +133,8 @@ final class TicketListApiControllerCurrentStateEmergencyTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with invalid emergency filter diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateTest.php index 15c8bcf51..5813c85ae 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerCurrentStateTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -89,7 +90,8 @@ final class TicketListApiControllerCurrentStateTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with person filter @@ -131,7 +133,8 @@ final class TicketListApiControllerCurrentStateTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with person filter diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerMotivesTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerMotivesTest.php index 858a352b3..846bb9bfb 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerMotivesTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerMotivesTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -94,7 +95,8 @@ final class TicketListApiControllerMotivesTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with multiple motives filter @@ -160,7 +162,8 @@ final class TicketListApiControllerMotivesTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with single motive filter @@ -204,7 +207,8 @@ final class TicketListApiControllerMotivesTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with non-existent motive @@ -231,6 +235,7 @@ final class TicketListApiControllerMotivesTest extends TestCase $personRepository = $this->prophesize(PersonRepository::class); $motiveRepository = $this->prophesize(MotiveRepository::class); $userRepository = $this->prophesize(UserRepositoryInterface::class); + $centerRepository = $this->prophesize(CenterRepositoryInterface::class); // Create controller $controller = new TicketListApiController( @@ -243,7 +248,8 @@ final class TicketListApiControllerMotivesTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $centerRepository->reveal(), ); // Create request with non-integer motive parameter diff --git a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerTest.php b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerTest.php index d9b8dd697..17facdea4 100644 --- a/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Controller/TicketListApiControllerTest.php @@ -13,6 +13,7 @@ namespace Chill\TicketBundle\Tests\Controller; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; use Chill\MainBundle\Pagination\PaginatorInterface; +use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Repository\UserGroupRepositoryInterface; use Chill\MainBundle\Serializer\Model\Collection; @@ -83,7 +84,8 @@ final class TicketListApiControllerTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request @@ -145,7 +147,8 @@ final class TicketListApiControllerTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with person filter @@ -185,7 +188,8 @@ final class TicketListApiControllerTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request @@ -228,7 +232,8 @@ final class TicketListApiControllerTest extends TestCase new MockClock(), new ParameterBag(['chill_ticket' => ['ticket' => ['response_time_exceeded_delay' => 'PT12H']]]), $userRepository->reveal(), - $this->prophesize(UserGroupRepositoryInterface::class)->reveal() + $this->prophesize(UserGroupRepositoryInterface::class)->reveal(), + $this->prophesize(CenterRepositoryInterface::class)->reveal() ); // Create request with person filter diff --git a/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php b/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php index 3635d3dc3..17684b06f 100644 --- a/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\TicketBundle\Tests\Repository; +use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserGroup; use Chill\PersonBundle\DataFixtures\Helper\RandomPersonHelperTrait; @@ -192,4 +193,19 @@ class TicketACLAwareRepositoryTest extends KernelTestCase self::assertIsArray($actual); } + + public function testFindByPersonCenter(): void + { + $centers = $this->entityManager->createQuery('SELECT c FROM '.Center::class.' c') + ->setMaxResults(2) + ->getResult(); + + if ([] === $centers) { + throw new \UnexpectedValueException('No centers found'); + } + + $actual = $this->repository->findTickets(['byPersonCenter' => $centers]); + + self::assertIsArray($actual); + } }