From 0a77e20ee6678c3ea011d82794a8acc2447bbe31 Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Mon, 21 Sep 2026 21:51:43 +0000 Subject: [PATCH 1/3] =?UTF-8?q?Migration=20de=20l'entit=C3=A9=20SponsorTic?= =?UTF-8?q?ket=20de=20Ting=20vers=20Doctrine=20(#2383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phpstan-baseline.php | 54 ---- .../Admin/Event/DeleteSponsorTicketAction.php | 4 +- .../Admin/Event/ResendSponsorTokenAction.php | 4 +- .../Event/SendLastCallSponsorTokenAction.php | 6 +- .../Admin/Event/SponsorTicketAction.php | 29 +- .../Event/SponsorScan/DeleteAction.php | 4 +- .../Event/SponsorScan/ExportAction.php | 2 +- .../Event/SponsorScan/FlashAction.php | 6 +- .../Event/SponsorScan/IndexAction.php | 2 +- .../Event/SponsorScan/NewAction.php | 2 +- .../SponsorScan/SponsorScanController.php | 8 +- .../Event/Ticket/SponsorTicketAction.php | 6 +- .../Event/Ticket/SponsorTicketFormAction.php | 4 +- .../Repository/SponsorTicketRepository.php | 31 +++ .../AppBundle/Event/Entity/SponsorTicket.php | 64 +++++ .../AppBundle/Event/Form/SponsorTokenType.php | 4 +- .../AppBundle/Event/Model/InvoiceFactory.php | 7 +- .../Repository/SponsorScanRepository.php | 4 +- .../Repository/SponsorTicketRepository.php | 104 ------- .../AppBundle/Event/Model/SponsorTicket.php | 261 ------------------ .../AppBundle/Event/Model/TicketFactory.php | 6 +- .../Event/Ticket/SponsorTicketHelper.php | 10 +- .../Event/Ticket/SponsorTokenMail.php | 12 +- .../admin/event/sponsor_ticket.html.twig | 4 +- templates/event/sponsor/scan.html.twig | 2 +- templates/event/ticket/sponsor.html.twig | 2 +- .../Admin/Events/TokensSponsors.feature | 4 +- .../SponsorTicketRepositoryTest.php | 64 +++++ 28 files changed, 228 insertions(+), 482 deletions(-) create mode 100644 sources/AppBundle/Event/Entity/Repository/SponsorTicketRepository.php create mode 100644 sources/AppBundle/Event/Entity/SponsorTicket.php delete mode 100644 sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php delete mode 100644 sources/AppBundle/Event/Model/SponsorTicket.php create mode 100644 tests/integration/AppBundle/Event/Entity/Repository/SponsorTicketRepositoryTest.php diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 2eb8c8980..718b9b751 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -3067,36 +3067,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SpecialPriceAction.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Cannot call method getId\\(\\) on AppBundle\\\\Event\\\\Model\\\\SponsorTicket\\|null\\.$#', - 'identifier' => 'method.nonObject', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Cannot call method setEditedOn\\(\\) on AppBundle\\\\Event\\\\Model\\\\SponsorTicket\\|null\\.$#', - 'identifier' => 'method.nonObject', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$entity of method CCMBenchmark\\\\Ting\\\\Repository\\\\Repository\\\\:\\:save\\(\\) expects AppBundle\\\\Event\\\\Model\\\\SponsorTicket, AppBundle\\\\Event\\\\Model\\\\SponsorTicket\\|null given\\.$#', - 'identifier' => 'argument.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$idForum of method AppBundle\\\\Event\\\\Model\\\\SponsorTicket\\:\\:setIdForum\\(\\) expects int, int\\|null given\\.$#', - 'identifier' => 'argument.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$sponsorTicket of method AppBundle\\\\Event\\\\Ticket\\\\SponsorTokenMail\\:\\:sendNotification\\(\\) expects AppBundle\\\\Event\\\\Model\\\\SponsorTicket, AppBundle\\\\Event\\\\Model\\\\SponsorTicket\\|null given\\.$#', - 'identifier' => 'argument.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php', -]; $ignoreErrors[] = [ 'message' => '#^Cannot access offset \'n\' on mixed\\.$#', 'identifier' => 'offsetAccess.nonOffsetAccessible', @@ -6385,30 +6355,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Event/Model/Repository/SponsorScanRepository.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Event\\\\Model\\\\Repository\\\\SponsorTicketRepository\\:\\:getByEvent\\(\\) return type with generic interface CCMBenchmark\\\\Ting\\\\Repository\\\\CollectionInterface does not specify its types\\: T$#', - 'identifier' => 'missingType.generics', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Event\\\\Model\\\\Repository\\\\SponsorTicketRepository\\:\\:initMetadata\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Event\\\\Model\\\\Repository\\\\SponsorTicketRepository\\:\\:initMetadata\\(\\) should return M of CCMBenchmark\\\\Ting\\\\Repository\\\\Metadata but returns CCMBenchmark\\\\Ting\\\\Repository\\\\Metadata\\\\.$#', - 'identifier' => 'return.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$databaseName of method CCMBenchmark\\\\Ting\\\\Repository\\\\Metadata\\\\:\\:setDatabase\\(\\) expects string, mixed given\\.$#', - 'identifier' => 'argument.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Event\\\\Model\\\\Repository\\\\TalkInvitationRepository\\:\\:getPendingInvitationsByTalkId\\(\\) has parameter \\$talkId with no type specified\\.$#', 'identifier' => 'missingType.parameter', diff --git a/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php b/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php index b4552e25b..5b9469d12 100644 --- a/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php +++ b/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php @@ -4,7 +4,7 @@ namespace AppBundle\Controller\Admin\Event; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Ticket\SponsorTicketHelper; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -19,7 +19,7 @@ public function __construct( public function __invoke(Request $request, int $tokenId): Response { - $token = $this->sponsorTicketRepository->get($tokenId); + $token = $this->sponsorTicketRepository->find($tokenId); if ($token === null) { throw $this->createNotFoundException(sprintf('Could not find token with id: %s', $tokenId)); } diff --git a/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php b/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php index fc161cea2..63f5f8fcf 100644 --- a/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php +++ b/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php @@ -5,7 +5,7 @@ namespace AppBundle\Controller\Admin\Event; use AppBundle\Event\AdminEventSelection; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Ticket\SponsorTokenMail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -20,7 +20,7 @@ public function __construct( public function __invoke(Request $request, AdminEventSelection $eventSelection): RedirectResponse { - $token = $this->sponsorTicketRepository->get($request->request->get('sponsor_token_id')); + $token = $this->sponsorTicketRepository->find($request->request->get('sponsor_token_id')); if ($token === null) { throw $this->createNotFoundException(sprintf('Could not find token with id: %s', $request->request->get('sponsor_token_id'))); } diff --git a/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php b/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php index 3202b1e26..2d6102019 100644 --- a/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php @@ -5,8 +5,8 @@ namespace AppBundle\Controller\Admin\Event; use AppBundle\Controller\Event\EventActionHelper; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; -use AppBundle\Event\Model\SponsorTicket; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\SponsorTicket; use AppBundle\Event\Ticket\SponsorTokenMail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -24,7 +24,7 @@ public function __invoke(Request $request): RedirectResponse { $event = $this->eventActionHelper->getFromRequest('id', false)->event; /** @var SponsorTicket[] $tokens */ - $tokens = $this->sponsorTicketRepository->getByEvent($event); + $tokens = $this->sponsorTicketRepository->findByEventId((int) $event->getId()); $mailSent = 0; foreach ($tokens as $token) { diff --git a/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php b/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php index de2ed6a5b..9a1261aa4 100644 --- a/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php @@ -5,12 +5,12 @@ namespace AppBundle\Controller\Admin\Event; use AppBundle\Event\AdminEventSelection; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\SponsorTicket; use AppBundle\Event\Form\SponsorTokenType; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; -use AppBundle\Event\Model\SponsorTicket; use AppBundle\Event\Ticket\SponsorTokenMail; use AppBundle\Security\Authentication; -use DateTime; +use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -26,24 +26,27 @@ public function __construct( public function __invoke(Request $request, AdminEventSelection $eventSelection): Response { $event = $eventSelection->event; - $tokens = $this->sponsorTicketRepository->getByEvent($event); + $tokens = $this->sponsorTicketRepository->findByEventId((int) $event->getId()); $edit = $request->query->has('ticket'); + $now = new DateTimeImmutable(); if ($edit) { - $newToken = $this->sponsorTicketRepository->get($request->query->get('ticket')); - $newToken->setEditedOn(new DateTime()); + $newToken = $this->sponsorTicketRepository->find($request->query->get('ticket')); + if ($newToken === null) { + throw $this->createNotFoundException('Could not find token'); + } + $newToken->editedOn = $now; } else { $newToken = new SponsorTicket(); - $newToken - ->setToken(base64_encode(random_bytes(30))) - ->setIdForum($event->getId()) - ->setCreatedOn(new DateTime()) - ->setEditedOn(new DateTime()) - ->setCreatorId($this->authentication->getAfupUser()->getId()); + $newToken->token = base64_encode(random_bytes(30)); + $newToken->eventId = (int) $event->getId(); + $newToken->createdOn = $now; + $newToken->editedOn = $now; + $newToken->creatorId = $this->authentication->getAfupUser()->getId(); } $form = $this->createForm(SponsorTokenType::class, $newToken); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - if ($newToken->getId() === null) { + if ($newToken->id === null) { $this->sponsorTokenMail->sendNotification($newToken); } $this->sponsorTicketRepository->save($newToken); diff --git a/sources/AppBundle/Controller/Event/SponsorScan/DeleteAction.php b/sources/AppBundle/Controller/Event/SponsorScan/DeleteAction.php index 4524b4e8b..9b9badc07 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/DeleteAction.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/DeleteAction.php @@ -7,7 +7,7 @@ use AppBundle\Controller\Event\EventActionHelper; use AppBundle\Controller\Exception\InvalidSponsorTokenException; use AppBundle\Event\Model\Repository\SponsorScanRepository; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Model\SponsorScan; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -32,7 +32,7 @@ public function __invoke(Request $request, string $eventSlug, string $scanId): R return $this->redirectToRoute('sponsor_ticket_home', ['eventSlug' => $eventSlug]); } - $scan = $this->sponsorScanRepository->getOneBy(['sponsorTicketId' => $sponsorTicket->getId(), 'id' => $scanId]); + $scan = $this->sponsorScanRepository->getOneBy(['sponsorTicketId' => $sponsorTicket->id, 'id' => $scanId]); if ($scan instanceof SponsorScan) { $scan->setDeletedOn(new \DateTime('now')); diff --git a/sources/AppBundle/Controller/Event/SponsorScan/ExportAction.php b/sources/AppBundle/Controller/Event/SponsorScan/ExportAction.php index f6c7b19ed..4d2e150fa 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/ExportAction.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/ExportAction.php @@ -7,7 +7,7 @@ use AppBundle\Controller\Event\EventActionHelper; use AppBundle\Controller\Exception\InvalidSponsorTokenException; use AppBundle\Event\Model\Repository\SponsorScanRepository; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/sources/AppBundle/Controller/Event/SponsorScan/FlashAction.php b/sources/AppBundle/Controller/Event/SponsorScan/FlashAction.php index 4941a8b34..636f5e662 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/FlashAction.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/FlashAction.php @@ -7,7 +7,7 @@ use AppBundle\Controller\Event\EventActionHelper; use AppBundle\Controller\Exception\InvalidSponsorTokenException; use AppBundle\Event\Model\Repository\SponsorScanRepository; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Model\Repository\TicketRepository; use AppBundle\Event\Model\SponsorScan; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -42,7 +42,7 @@ public function __invoke(Request $request, string $code, string $eventSlug): Red return $this->redirectToRoute('sponsor_scan', ['eventSlug' => $eventSlug]); } - $scan = $this->sponsorScanRepository->getOneBy(['sponsorTicketId' => $sponsorTicket->getId(), 'ticketId' => $ticket->getId()]); + $scan = $this->sponsorScanRepository->getOneBy(['sponsorTicketId' => $sponsorTicket->id, 'ticketId' => $ticket->getId()]); if ($scan instanceof SponsorScan && $scan->getDeletedOn() === null) { $this->addFlash('error', 'Code déjà scanné.'); @@ -51,7 +51,7 @@ public function __invoke(Request $request, string $code, string $eventSlug): Red if (!$scan instanceof SponsorScan) { $scan = new SponsorScan() - ->setSponsorTicketId($sponsorTicket->getId()) + ->setSponsorTicketId($sponsorTicket->id) ->setTicketId($ticket->getId()); } diff --git a/sources/AppBundle/Controller/Event/SponsorScan/IndexAction.php b/sources/AppBundle/Controller/Event/SponsorScan/IndexAction.php index 4c93ed5f8..60521f8ba 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/IndexAction.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/IndexAction.php @@ -7,7 +7,7 @@ use AppBundle\Controller\Event\EventActionHelper; use AppBundle\Controller\Exception\InvalidSponsorTokenException; use AppBundle\Event\Model\Repository\SponsorScanRepository; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/sources/AppBundle/Controller/Event/SponsorScan/NewAction.php b/sources/AppBundle/Controller/Event/SponsorScan/NewAction.php index d42698dc0..36df45e74 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/NewAction.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/NewAction.php @@ -7,7 +7,7 @@ use AppBundle\Controller\Event\EventActionHelper; use AppBundle\Controller\Exception\InvalidSponsorTokenException; use AppBundle\Event\Form\SponsorScanType; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/sources/AppBundle/Controller/Event/SponsorScan/SponsorScanController.php b/sources/AppBundle/Controller/Event/SponsorScan/SponsorScanController.php index 5386b12d9..9e222f322 100644 --- a/sources/AppBundle/Controller/Event/SponsorScan/SponsorScanController.php +++ b/sources/AppBundle/Controller/Event/SponsorScan/SponsorScanController.php @@ -5,8 +5,8 @@ namespace AppBundle\Controller\Event\SponsorScan; use AppBundle\Controller\Exception\InvalidSponsorTokenException; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; -use AppBundle\Event\Model\SponsorTicket; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\SponsorTicket; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -20,12 +20,12 @@ protected function checkSponsorTicket(Request $request): SponsorTicket throw new InvalidSponsorTokenException('Merci de renseigner votre token.'); } - $sponsorTicket = $this->sponsorTicketRepository->get($request->getSession()->get('sponsor_ticket_id')); + $sponsorTicket = $this->sponsorTicketRepository->find($request->getSession()->get('sponsor_ticket_id')); if ($sponsorTicket === null) { throw new InvalidSponsorTokenException('Token invalide.'); } - if (!$sponsorTicket->getQrCodesScannerAvailable()) { + if (!$sponsorTicket->qrCodesScannerAvailable) { throw new InvalidSponsorTokenException('Accès non autorisé.'); } diff --git a/sources/AppBundle/Controller/Event/Ticket/SponsorTicketAction.php b/sources/AppBundle/Controller/Event/Ticket/SponsorTicketAction.php index 51ba5fc9f..5d3907d8e 100644 --- a/sources/AppBundle/Controller/Event/Ticket/SponsorTicketAction.php +++ b/sources/AppBundle/Controller/Event/Ticket/SponsorTicketAction.php @@ -5,7 +5,7 @@ namespace AppBundle\Controller\Event\Ticket; use AppBundle\Controller\Event\EventActionHelper; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -41,13 +41,13 @@ public function __invoke(Request $request, $eventSlug): Response $token = $request->request->get('sponsor_token'); $limiter = $this->sponsorTokenLimiter->create($request->getClientIp()); $rateLimit = $limiter->consume(1); - $sponsorTicket = $this->sponsorTicketRepository->getOneBy(['token' => $token]); + $sponsorTicket = $this->sponsorTicketRepository->findOneBy(['token' => $token]); if (!$rateLimit->isAccepted() || $sponsorTicket === null) { // Même message que si le token n'existe pas, pour ne pas révéler le blocage $errors[] = 'Ce token n\'existe pas.'; } else { $limiter->reset(); - $session->set('sponsor_ticket_id', $sponsorTicket->getId()); + $session->set('sponsor_ticket_id', $sponsorTicket->id); return $this->redirectToRoute('sponsor_ticket_form', ['eventSlug' => $eventSlug]); } diff --git a/sources/AppBundle/Controller/Event/Ticket/SponsorTicketFormAction.php b/sources/AppBundle/Controller/Event/Ticket/SponsorTicketFormAction.php index 4122a35b4..c04050f0a 100644 --- a/sources/AppBundle/Controller/Event/Ticket/SponsorTicketFormAction.php +++ b/sources/AppBundle/Controller/Event/Ticket/SponsorTicketFormAction.php @@ -8,7 +8,7 @@ use AppBundle\Email\Emails; use AppBundle\Email\Mailer\MailUser; use AppBundle\Event\Form\SponsorTicketType; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Model\Repository\TicketRepository; use AppBundle\Event\Model\TicketFactory; use AppBundle\Event\Ticket\SponsorTicketHelper; @@ -39,7 +39,7 @@ public function __invoke(Request $request, $eventSlug): Response return $this->redirectToRoute('sponsor_ticket_home', ['eventSlug' => $eventSlug]); } - $sponsorTicket = $this->sponsorTicketRepository->get($request->getSession()->get('sponsor_ticket_id')); + $sponsorTicket = $this->sponsorTicketRepository->find($request->getSession()->get('sponsor_ticket_id')); if ($sponsorTicket === null) { $this->addFlash('error', 'Token invalide'); return $this->redirectToRoute('sponsor_ticket_home', ['eventSlug' => $eventSlug]); diff --git a/sources/AppBundle/Event/Entity/Repository/SponsorTicketRepository.php b/sources/AppBundle/Event/Entity/Repository/SponsorTicketRepository.php new file mode 100644 index 000000000..f15261ef7 --- /dev/null +++ b/sources/AppBundle/Event/Entity/Repository/SponsorTicketRepository.php @@ -0,0 +1,31 @@ + + */ +final class SponsorTicketRepository extends EntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, SponsorTicket::class); + } + + /** + * @return list + */ + public function findByEventId(int $eventId): array + { + /** @var list $sponsorTickets */ + $sponsorTickets = $this->findBy(['eventId' => $eventId]); + + return $sponsorTickets; + } +} diff --git a/sources/AppBundle/Event/Entity/SponsorTicket.php b/sources/AppBundle/Event/Entity/SponsorTicket.php new file mode 100644 index 000000000..fba0e2017 --- /dev/null +++ b/sources/AppBundle/Event/Entity/SponsorTicket.php @@ -0,0 +1,64 @@ +maxInvitations - $this->usedInvitations; + } +} diff --git a/sources/AppBundle/Event/Form/SponsorTokenType.php b/sources/AppBundle/Event/Form/SponsorTokenType.php index 3d0efe9a8..3659a23f9 100644 --- a/sources/AppBundle/Event/Form/SponsorTokenType.php +++ b/sources/AppBundle/Event/Form/SponsorTokenType.php @@ -4,7 +4,7 @@ namespace AppBundle\Event\Form; -use AppBundle\Event\Model\SponsorTicket; +use AppBundle\Event\Entity\SponsorTicket; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\EmailType; @@ -18,7 +18,7 @@ class SponsorTokenType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder - ->add('company', TextType::class, [ + ->add('societe', TextType::class, [ 'label' => 'Sponsor (société)', ]) ->add('contactEmail', EmailType::class, [ diff --git a/sources/AppBundle/Event/Model/InvoiceFactory.php b/sources/AppBundle/Event/Model/InvoiceFactory.php index 51b12ba73..5eca07ca1 100644 --- a/sources/AppBundle/Event/Model/InvoiceFactory.php +++ b/sources/AppBundle/Event/Model/InvoiceFactory.php @@ -4,6 +4,7 @@ namespace AppBundle\Event\Model; +use AppBundle\Event\Entity\SponsorTicket; use AppBundle\Event\Model\Repository\InvoiceRepository; class InvoiceFactory @@ -12,7 +13,7 @@ public function __construct(private readonly InvoiceRepository $invoiceRepositor public function createInvoiceFromSponsorTicket(SponsorTicket $sponsorTicket) { - $reference = 'SPONSOR-' . $sponsorTicket->getIdForum() . '-' . $sponsorTicket->getId(); + $reference = 'SPONSOR-' . $sponsorTicket->eventId . '-' . $sponsorTicket->id; $invoice = $this->invoiceRepository->get($reference); if ($invoice !== null) { return $invoice; @@ -20,10 +21,10 @@ public function createInvoiceFromSponsorTicket(SponsorTicket $sponsorTicket) $invoice = new Invoice(); $invoice - ->setForumId($sponsorTicket->getIdForum()) + ->setForumId($sponsorTicket->eventId) ->setAmount(0) ->setReference($reference) - ->setCompany($sponsorTicket->getCompany()) + ->setCompany($sponsorTicket->societe) ->setPaymentType(Ticket::PAYMENT_NONE) ->setEmail('bureau@afup.org') ->setAddress('N/A') diff --git a/sources/AppBundle/Event/Model/Repository/SponsorScanRepository.php b/sources/AppBundle/Event/Model/Repository/SponsorScanRepository.php index accd44130..1e9cc9314 100644 --- a/sources/AppBundle/Event/Model/Repository/SponsorScanRepository.php +++ b/sources/AppBundle/Event/Model/Repository/SponsorScanRepository.php @@ -4,8 +4,8 @@ namespace AppBundle\Event\Model\Repository; +use AppBundle\Event\Entity\SponsorTicket; use AppBundle\Event\Model\SponsorScan; -use AppBundle\Event\Model\SponsorTicket; use CCMBenchmark\Ting\Repository\HydratorArray; use CCMBenchmark\Ting\Repository\Metadata; use CCMBenchmark\Ting\Repository\MetadataInitializer; @@ -31,7 +31,7 @@ public function getBySponsorTicket(SponsorTicket $sponsorTicket) ORDER BY afup_forum_sponsor_scan.created_on DESC'; return $this->getPreparedQuery($sql) - ->setParams(['sponsorTicketId' => $sponsorTicket->getId()]) + ->setParams(['sponsorTicketId' => $sponsorTicket->id]) ->query($this->getCollection(new HydratorArray())); } diff --git a/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php b/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php deleted file mode 100644 index e724a4f79..000000000 --- a/sources/AppBundle/Event/Model/Repository/SponsorTicketRepository.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ -class SponsorTicketRepository extends Repository implements MetadataInitializer -{ - /** - * @return CollectionInterface - */ - public function getByEvent(Event $event) - { - return $this->getBy(['idForum' => $event->getId()]); - } - - /** - * @inheritDoc - */ - public static function initMetadata(SerializerFactoryInterface $serializerFactory, array $options = []) - { - $metadata = new Metadata($serializerFactory); - - $metadata->setEntity(SponsorTicket::class); - $metadata->setConnectionName('main'); - $metadata->setDatabase($options['database']); - $metadata->setTable('afup_forum_sponsors_tickets'); - - $metadata - ->addField([ - 'columnName' => 'id', - 'fieldName' => 'id', - 'primary' => true, - 'autoincrement' => true, - 'type' => 'int', - ]) - ->addField([ - 'columnName' => 'company', - 'fieldName' => 'company', - 'type' => 'string', - ]) - ->addField([ - 'columnName' => 'token', - 'fieldName' => 'token', - 'type' => 'string', - ]) - ->addField([ - 'columnName' => 'contact_email', - 'fieldName' => 'contactEmail', - 'type' => 'string', - ]) - ->addField([ - 'columnName' => 'max_invitations', - 'fieldName' => 'maxInvitations', - 'type' => 'int', - ]) - ->addField([ - 'columnName' => 'used_invitations', - 'fieldName' => 'usedInvitations', - 'type' => 'int', - ]) - ->addField([ - 'columnName' => 'id_forum', - 'fieldName' => 'idForum', - 'type' => 'int', - ]) - ->addField([ - 'columnName' => 'created_on', - 'fieldName' => 'createdOn', - 'type' => 'datetime', - ]) - ->addField([ - 'columnName' => 'edited_on', - 'fieldName' => 'editedOn', - 'type' => 'datetime', - ]) - ->addField([ - 'columnName' => 'creator_id', - 'fieldName' => 'creatorId', - 'type' => 'int', - ]) - ->addField([ - 'columnName' => 'qr_codes_scanner_available', - 'fieldName' => 'qrCodesScannerAvailable', - 'type' => 'bool', - 'serializer' => Boolean::class, - ]) - ; - - return $metadata; - } -} diff --git a/sources/AppBundle/Event/Model/SponsorTicket.php b/sources/AppBundle/Event/Model/SponsorTicket.php deleted file mode 100644 index c4c814512..000000000 --- a/sources/AppBundle/Event/Model/SponsorTicket.php +++ /dev/null @@ -1,261 +0,0 @@ -id; - } - - public function setId(int $id): self - { - $this->propertyChanged('id', $this->id, $id); - $this->id = $id; - return $this; - } - - /** - * @return string - */ - public function getCompany() - { - return $this->company; - } - - /** - * @param string $company - */ - public function setCompany($company): self - { - $this->propertyChanged('company', $this->company, $company); - $this->company = $company; - return $this; - } - - /** - * @return string - */ - public function getToken() - { - return $this->token; - } - - /** - * @param string $token - */ - public function setToken($token): self - { - $this->propertyChanged('token', $this->token, $token); - $this->token = $token; - return $this; - } - - /** - * @return string - */ - public function getContactEmail() - { - return $this->contactEmail; - } - - /** - * @param string $contactEmail - */ - public function setContactEmail($contactEmail): self - { - $this->propertyChanged('contactEmail', $this->contactEmail, $contactEmail); - $this->contactEmail = $contactEmail; - return $this; - } - - /** - * @return int - */ - public function getMaxInvitations() - { - return $this->maxInvitations; - } - - /** - * @param int $maxInvitations - */ - public function setMaxInvitations($maxInvitations): self - { - $this->propertyChanged('maxInvitations', $this->maxInvitations, $maxInvitations); - $this->maxInvitations = $maxInvitations; - return $this; - } - - /** - * @return int - */ - public function getUsedInvitations() - { - return $this->usedInvitations; - } - - /** - * @param int $usedInvitations - */ - public function setUsedInvitations($usedInvitations): self - { - $this->propertyChanged('usedInvitations', $this->usedInvitations, $usedInvitations); - $this->usedInvitations = $usedInvitations; - return $this; - } - - /** - * @return int - */ - public function getIdForum() - { - return $this->idForum; - } - - /** - * @param int $idForum - */ - public function setIdForum($idForum): self - { - $this->propertyChanged('idForum', $this->idForum, $idForum); - $this->idForum = $idForum; - return $this; - } - - /** - * @return \DateTime - */ - public function getCreatedOn(): ?\DateTime - { - return $this->createdOn; - } - - public function setCreatedOn(\DateTime $createdOn): self - { - $this->propertyChanged('createdOn', $this->createdOn, $createdOn); - $this->createdOn = $createdOn; - return $this; - } - - /** - * @return \DateTime - */ - public function getEditedOn(): ?\DateTime - { - return $this->editedOn; - } - - public function setEditedOn(\DateTime $editedOn): self - { - $this->propertyChanged('editedOn', $this->editedOn, $editedOn); - $this->editedOn = $editedOn; - return $this; - } - - /** - * @return int - */ - public function getCreatorId() - { - return $this->creatorId; - } - - /** - * @param int $creatorId - */ - public function setCreatorId($creatorId): self - { - $this->propertyChanged('creatorId', $this->creatorId, $creatorId); - $this->creatorId = $creatorId; - return $this; - } - - /** - * @return int - */ - public function getPendingInvitations() - { - return $this->maxInvitations - $this->usedInvitations; - } - - /** - * @return bool - */ - public function getQrCodesScannerAvailable() - { - return $this->qrCodesScannerAvailable; - } - - /** - * @param bool $qrCodesScannerAvailable - */ - public function setQrCodesScannerAvailable($qrCodesScannerAvailable): self - { - $this->propertyChanged('qrCodesScannerAvailable', $this->qrCodesScannerAvailable, $qrCodesScannerAvailable); - $this->qrCodesScannerAvailable = $qrCodesScannerAvailable; - return $this; - } -} diff --git a/sources/AppBundle/Event/Model/TicketFactory.php b/sources/AppBundle/Event/Model/TicketFactory.php index 73d86853b..d3afc3227 100644 --- a/sources/AppBundle/Event/Model/TicketFactory.php +++ b/sources/AppBundle/Event/Model/TicketFactory.php @@ -4,16 +4,18 @@ namespace AppBundle\Event\Model; +use AppBundle\Event\Entity\SponsorTicket; + class TicketFactory { public function createTicketFromSponsorTicket(SponsorTicket $sponsorTicket): Ticket { $ticket = new Ticket(); $ticket - ->setForumId($sponsorTicket->getIdForum()) + ->setForumId($sponsorTicket->eventId) ->setAmount(0) ->setCompanyCitation(true) - ->setReference('SPONSOR-' . $sponsorTicket->getIdForum() . '-' . $sponsorTicket->getId()) + ->setReference('SPONSOR-' . $sponsorTicket->eventId . '-' . $sponsorTicket->id) ->setInvoiceStatus(Ticket::INVOICE_SENT) ->setStatus(Ticket::STATUS_PAID) ->setTicketTypeId(Ticket::TYPE_SPONSOR) diff --git a/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php b/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php index bf3e233ca..eddeacd8a 100644 --- a/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php +++ b/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php @@ -5,10 +5,10 @@ namespace AppBundle\Event\Ticket; use AppBundle\Event\Model\InvoiceFactory; +use AppBundle\Event\Entity\Repository\SponsorTicketRepository; use AppBundle\Event\Model\Repository\InvoiceRepository; -use AppBundle\Event\Model\Repository\SponsorTicketRepository; use AppBundle\Event\Model\Repository\TicketRepository; -use AppBundle\Event\Model\SponsorTicket; +use AppBundle\Event\Entity\SponsorTicket; use AppBundle\Event\Model\Ticket; use CCMBenchmark\Ting\Exception; @@ -29,8 +29,8 @@ public function addTicketToSponsor(SponsorTicket $sponsorTicket, Ticket $ticket) $this->invoiceRepository->save($invoice); if ($ticket->getId() === null) { - // This is a new ticket, so we update the number of tickets created for this sponsor - $sponsorTicket->setUsedInvitations($sponsorTicket->getUsedInvitations() + 1); + // Nouveau ticket : on incrémente le compteur d'invitations utilisées du sponsor + $sponsorTicket->usedInvitations++; } $this->ticketRepository->save($ticket); @@ -50,7 +50,7 @@ public function removeTicketFromSponsor(SponsorTicket $sponsorTicket, Ticket $ti try { $this->ticketRepository->startTransaction(); $this->ticketRepository->delete($ticket); - $sponsorTicket->setUsedInvitations($sponsorTicket->getUsedInvitations() - 1); + $sponsorTicket->usedInvitations--; $this->sponsorTicketRepository->save($sponsorTicket); $this->ticketRepository->commit(); } catch (Exception) { diff --git a/sources/AppBundle/Event/Ticket/SponsorTokenMail.php b/sources/AppBundle/Event/Ticket/SponsorTokenMail.php index fae3abcca..063a74cb4 100644 --- a/sources/AppBundle/Event/Ticket/SponsorTokenMail.php +++ b/sources/AppBundle/Event/Ticket/SponsorTokenMail.php @@ -10,7 +10,7 @@ use AppBundle\Email\Mailer\Message; use AppBundle\Event\Model\Event; use AppBundle\Event\Model\Repository\EventRepository; -use AppBundle\Event\Model\SponsorTicket; +use AppBundle\Event\Entity\SponsorTicket; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RouterInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -34,7 +34,7 @@ public function sendNotification(SponsorTicket $sponsorTicket, $lastCall = false /** * @var Event $event */ - $event = $this->eventRepository->get($sponsorTicket->getIdForum()); + $event = $this->eventRepository->get($sponsorTicket->eventId); $textLabel = 'mail.sponsorTicket.text'; $subjectLabel = "mail.sponsorTicket.subject"; @@ -47,9 +47,9 @@ public function sendNotification(SponsorTicket $sponsorTicket, $lastCall = false $text = $this->translator->trans( $textLabel, [ - '%count%' => $sponsorTicket->getMaxInvitations(), - '%token%' => $sponsorTicket->getToken(), - '%places%' => $sponsorTicket->getMaxInvitations(), + '%count%' => $sponsorTicket->maxInvitations, + '%token%' => $sponsorTicket->token, + '%places%' => $sponsorTicket->maxInvitations, '%event%' => $event->getTitle(), '%link%' => $this->router->generate( 'sponsor_ticket_home', @@ -63,7 +63,7 @@ public function sendNotification(SponsorTicket $sponsorTicket, $lastCall = false return $this->mailer->sendTransactional(new Message( $this->translator->trans($subjectLabel, ['%event%' => $event->getTitle()]), MailUserFactory::afup(), - new MailUser($sponsorTicket->getContactEmail(), $sponsorTicket->getCompany()), + new MailUser($sponsorTicket->contactEmail, $sponsorTicket->societe), ), $text); } } diff --git a/templates/admin/event/sponsor_ticket.html.twig b/templates/admin/event/sponsor_ticket.html.twig index 71b1959b2..e94e4c9e9 100644 --- a/templates/admin/event/sponsor_ticket.html.twig +++ b/templates/admin/event/sponsor_ticket.html.twig @@ -59,7 +59,7 @@ {% set totalInvitations = totalInvitations + token.maxInvitations %} {% set totalUsedInvitations = totalUsedInvitations + token.usedInvitations %} - {{ token.company }} + {{ token.societe }} {{ token.token }} {{ token.maxInvitations }} {{ token.usedInvitations }} @@ -159,7 +159,7 @@
{% if edit == true %} -

Modifier le token de {{ form.vars.value.company}}

+

Modifier le token de {{ form.vars.value.societe}}

{% else %}

Nouveau token

{% endif %} diff --git a/templates/event/sponsor/scan.html.twig b/templates/event/sponsor/scan.html.twig index 3c4face95..abbe93224 100644 --- a/templates/event/sponsor/scan.html.twig +++ b/templates/event/sponsor/scan.html.twig @@ -3,7 +3,7 @@ {% block content %}
-

{{ 'QR Codes'|trans }} : {{ event.title }} - {{ sponsorTicket.company }}

+

{{ 'QR Codes'|trans }} : {{ event.title }} - {{ sponsorTicket.societe }}

{% trans %}SCANNEUR DE QR CODES{% endtrans %}

diff --git a/templates/event/ticket/sponsor.html.twig b/templates/event/ticket/sponsor.html.twig index 328210421..0e357a7a6 100644 --- a/templates/event/ticket/sponsor.html.twig +++ b/templates/event/ticket/sponsor.html.twig @@ -8,7 +8,7 @@ {% block content %}
-

{{ 'Billetterie sponsor'|trans }}: {{ event.title }} - {{ sponsorTicket.company }}

+

{{ 'Billetterie sponsor'|trans }}: {{ event.title }} - {{ sponsorTicket.societe }}

{% if sponsorTicket.qrCodesScannerAvailable %}

{% trans %}SCANNEUR DE QR CODES{% endtrans %}

diff --git a/tests/behat/features/Admin/Events/TokensSponsors.feature b/tests/behat/features/Admin/Events/TokensSponsors.feature index f99cf12ca..a45b14e42 100644 --- a/tests/behat/features/Admin/Events/TokensSponsors.feature +++ b/tests/behat/features/Admin/Events/TokensSponsors.feature @@ -12,7 +12,7 @@ Feature: Administration - Évènements - Tokens Sponsors And I follow "Tokens sponsors" Then the ".content h2" element should contain "Liste des tokens sponsors pour forum" # ajout d'un token - When I fill in "sponsor_token[company]" with "Ma société" + When I fill in "sponsor_token[societe]" with "Ma société" And I fill in "sponsor_token[contactEmail]" with "testToken1@mail.com" And I fill in "sponsor_token[maxInvitations]" with "2" And I press "Enregistrer" @@ -69,7 +69,7 @@ Feature: Administration - Évènements - Tokens Sponsors And I follow "Tokens sponsors" Then the ".content h2" element should contain "Liste des tokens sponsors pour forum" # ajout d'un token - When I fill in "sponsor_token[company]" with "Ma société" + When I fill in "sponsor_token[societe]" with "Ma société" And I fill in "sponsor_token[contactEmail]" with "testToken1@mail.com" And I fill in "sponsor_token[maxInvitations]" with "2" And I press "Enregistrer" diff --git a/tests/integration/AppBundle/Event/Entity/Repository/SponsorTicketRepositoryTest.php b/tests/integration/AppBundle/Event/Entity/Repository/SponsorTicketRepositoryTest.php new file mode 100644 index 000000000..1e5cd57bd --- /dev/null +++ b/tests/integration/AppBundle/Event/Entity/Repository/SponsorTicketRepositoryTest.php @@ -0,0 +1,64 @@ +get(SponsorTicketRepository::class); + + $sponsorTicketRepository->save($this->buildSponsorTicket(42, 'Société ABC', 'TOKEN-ABC')); + $societeXyz = $this->buildSponsorTicket(42, 'Société XYZ', 'TOKEN-XYZ'); + $sponsorTicketRepository->save($societeXyz); + $sponsorTicketRepository->save($this->buildSponsorTicket(43, 'Société Autre', 'TOKEN-AUTRE')); + + $fromEvent = $sponsorTicketRepository->findByEventId(42); + self::assertCount(2, $fromEvent); + self::assertSame('Société ABC', $fromEvent[0]->societe); + self::assertSame('Société XYZ', $fromEvent[1]->societe); + + $found = $sponsorTicketRepository->find($societeXyz->id); + self::assertInstanceOf(SponsorTicket::class, $found); + self::assertSame('Société XYZ', $found->societe); + + $byToken = $sponsorTicketRepository->findOneBy(['token' => 'TOKEN-ABC']); + self::assertInstanceOf(SponsorTicket::class, $byToken); + self::assertSame(5, $byToken->maxInvitations); + self::assertSame(2, $byToken->getPendingInvitations()); + self::assertNull($sponsorTicketRepository->findOneBy(['token' => 'TOKEN-INTROUVABLE'])); + + $byToken->usedInvitations = 3; + $sponsorTicketRepository->save($byToken); + self::assertSame(2, $sponsorTicketRepository->find($byToken->id)->getPendingInvitations()); + + $id = $byToken->id; + $sponsorTicketRepository->delete($byToken); + self::assertNull($sponsorTicketRepository->find($id)); + } + + private function buildSponsorTicket(int $eventId, string $societe, string $token): SponsorTicket + { + $now = new \DateTimeImmutable(); + + $sponsorTicket = new SponsorTicket(); + $sponsorTicket->eventId = $eventId; + $sponsorTicket->societe = $societe; + $sponsorTicket->token = $token; + $sponsorTicket->contactEmail = 'contact@example.com'; + $sponsorTicket->maxInvitations = 5; + $sponsorTicket->usedInvitations = 3; + $sponsorTicket->createdOn = $now; + $sponsorTicket->editedOn = $now; + $sponsorTicket->creatorId = 1; + $sponsorTicket->qrCodesScannerAvailable = true; + + return $sponsorTicket; + } +} From 5564c37ed419e97b9e144796329ee04fdaac8797 Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Wed, 30 Sep 2026 20:58:13 +0000 Subject: [PATCH 2/3] Correction de la 500 sur soumission vide du formulaire des tokens sponsors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sur une soumission vide ou remplie d'espaces, le composant Form convertit la valeur en null, ce qui provoquait une erreur de typage sur les propriétés non nullables de SponsorTicket au lieu d'un message de validation. - empty_data => '' sur les champs texte de SponsorTokenType - empty_data => '0' sur maxInvitations (même classe de bug, Champ integer) - #Assert\NotBlank rétabli sur SponsorTicket::$societe (perdu dans la migration Ting) Retour de la review #2416 (vgreb). --- sources/AppBundle/Event/Entity/SponsorTicket.php | 1 + sources/AppBundle/Event/Form/SponsorTokenType.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sources/AppBundle/Event/Entity/SponsorTicket.php b/sources/AppBundle/Event/Entity/SponsorTicket.php index fba0e2017..3a31097ba 100644 --- a/sources/AppBundle/Event/Entity/SponsorTicket.php +++ b/sources/AppBundle/Event/Entity/SponsorTicket.php @@ -19,6 +19,7 @@ class SponsorTicket public ?int $id = null; #[ORM\Column(name: 'company', nullable: false)] + #[Assert\NotBlank] public string $societe; #[ORM\Column(length: 64, nullable: false)] diff --git a/sources/AppBundle/Event/Form/SponsorTokenType.php b/sources/AppBundle/Event/Form/SponsorTokenType.php index 3659a23f9..3f261fc78 100644 --- a/sources/AppBundle/Event/Form/SponsorTokenType.php +++ b/sources/AppBundle/Event/Form/SponsorTokenType.php @@ -20,13 +20,16 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $builder ->add('societe', TextType::class, [ 'label' => 'Sponsor (société)', + 'empty_data' => '', ]) ->add('contactEmail', EmailType::class, [ 'label' => 'Email de contact', + 'empty_data' => '', ]) - ->add('token', TextType::class) + ->add('token', TextType::class, ['empty_data' => '']) ->add('maxInvitations', IntegerType::class, [ 'label' => 'Nombre d\'invitations', + 'empty_data' => '0', ]) ->add('qrCodesScannerAvailable', CheckboxType::class, [ 'label' => 'Autoriser le scan de QR Codes', From cdeef2a1c86220ad7aa0a3c6a41a0a5954558b1a Mon Sep 17 00:00:00 2001 From: Baptiste Leduc Date: Mon, 12 Oct 2026 21:11:52 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Ajuste=20la=20r=C3=A9servation=20du=20compt?= =?UTF-8?q?eur=20d'invitations=20autour=20des=20transactions=20Ting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Event/Ticket/SponsorTicketHelper.php | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php b/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php index eddeacd8a..836f285bd 100644 --- a/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php +++ b/sources/AppBundle/Event/Ticket/SponsorTicketHelper.php @@ -24,20 +24,27 @@ public function __construct( public function addTicketToSponsor(SponsorTicket $sponsorTicket, Ticket $ticket): void { $invoice = $this->invoiceFactory->createInvoiceFromSponsorTicket($sponsorTicket); + $isNewTicket = $ticket->getId() === null; + + if ($isNewTicket) { + // Réservée hors transaction Ting (connexion Doctrine distincte) : + // en cas d'échec entre les deux écritures, le compteur surestime, sans risque de dépasser le quota + $sponsorTicket->usedInvitations++; + $this->sponsorTicketRepository->save($sponsorTicket); + } + try { $this->invoiceRepository->startTransaction(); $this->invoiceRepository->save($invoice); - - if ($ticket->getId() === null) { - // Nouveau ticket : on incrémente le compteur d'invitations utilisées du sponsor - $sponsorTicket->usedInvitations++; - } - $this->ticketRepository->save($ticket); - $this->sponsorTicketRepository->save($sponsorTicket); $this->invoiceRepository->commit(); } catch (Exception) { $this->invoiceRepository->rollback(); + + if ($isNewTicket) { + $sponsorTicket->usedInvitations--; + $this->sponsorTicketRepository->save($sponsorTicket); + } } } @@ -50,12 +57,17 @@ public function removeTicketFromSponsor(SponsorTicket $sponsorTicket, Ticket $ti try { $this->ticketRepository->startTransaction(); $this->ticketRepository->delete($ticket); - $sponsorTicket->usedInvitations--; - $this->sponsorTicketRepository->save($sponsorTicket); $this->ticketRepository->commit(); } catch (Exception) { $this->ticketRepository->rollback(); + + return; } + + // Libérée seulement après le commit Ting (connexion Doctrine distincte) : + // si cette écriture échoue, le compteur surestime, sans risque de dépasser le quota + $sponsorTicket->usedInvitations--; + $this->sponsorTicketRepository->save($sponsorTicket); } public function doesTicketBelongsToSponsor(SponsorTicket $sponsorTicket, Ticket $ticket): bool