Refactor AccountController: extract constants, reduce returns and cognitive complexity
- Add DQL_EXCLUDE_INVITATIONS, DQL_BB_EXCLUDE_INVITATIONS, CONTENT_TYPE_PDF constants - Reduce createAccreditation from 4 to 3 returns by combining validations - Extract collectAttestationBillets, buildAttestationStats, buildAttestationTicketDetails from eventAttestation to reduce cognitive complexity from 18 to under 15 - Remove unused $totalRevenue, duplicate $label, and securityKey from attestation details Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,9 @@ class AccountController extends AbstractController
|
|||||||
private const BREADCRUMB_ACCOUNT = ['name' => 'Mon compte', 'url' => '/mon-compte'];
|
private const BREADCRUMB_ACCOUNT = ['name' => 'Mon compte', 'url' => '/mon-compte'];
|
||||||
private const EVENT_BASE_URL = '/mon-compte/evenement/';
|
private const EVENT_BASE_URL = '/mon-compte/evenement/';
|
||||||
private const EVENT_CATEGORIES_SUFFIX = '/modifier?tab=categories';
|
private const EVENT_CATEGORIES_SUFFIX = '/modifier?tab=categories';
|
||||||
|
private const DQL_EXCLUDE_INVITATIONS = 'o.isInvitation = false OR o.isInvitation IS NULL';
|
||||||
|
private const DQL_BB_EXCLUDE_INVITATIONS = 'bb.isInvitation = false OR bb.isInvitation IS NULL';
|
||||||
|
private const CONTENT_TYPE_PDF = 'application/pdf';
|
||||||
|
|
||||||
#[Route('/mon-compte', name: 'app_account')]
|
#[Route('/mon-compte', name: 'app_account')]
|
||||||
public function index(Request $request, StripeService $stripeService, EntityManagerInterface $em, PaginatorInterface $paginator, EventIndexService $eventIndex): Response
|
public function index(Request $request, StripeService $stripeService, EntityManagerInterface $em, PaginatorInterface $paginator, EventIndexService $eventIndex): Response
|
||||||
@@ -445,7 +448,7 @@ class AccountController extends AbstractController
|
|||||||
->from(BilletOrder::class, 'bo')
|
->from(BilletOrder::class, 'bo')
|
||||||
->join('bo.billetBuyer', 'bb')
|
->join('bo.billetBuyer', 'bb')
|
||||||
->where('bo.billet IN (:ids)')
|
->where('bo.billet IN (:ids)')
|
||||||
->andWhere('bb.isInvitation = false OR bb.isInvitation IS NULL')
|
->andWhere(self::DQL_BB_EXCLUDE_INVITATIONS)
|
||||||
->setParameter('ids', $billetIds)
|
->setParameter('ids', $billetIds)
|
||||||
->groupBy('bo.billet')
|
->groupBy('bo.billet')
|
||||||
->getQuery()
|
->getQuery()
|
||||||
@@ -484,7 +487,7 @@ class AccountController extends AbstractController
|
|||||||
->leftJoin('o.items', 'i')
|
->leftJoin('o.items', 'i')
|
||||||
->where('o.event = :event')
|
->where('o.event = :event')
|
||||||
->andWhere('o.status = :status')
|
->andWhere('o.status = :status')
|
||||||
->andWhere('o.isInvitation = false OR o.isInvitation IS NULL')
|
->andWhere(self::DQL_EXCLUDE_INVITATIONS)
|
||||||
->setParameter('event', $event)
|
->setParameter('event', $event)
|
||||||
->setParameter('status', BilletBuyer::STATUS_PAID)
|
->setParameter('status', BilletBuyer::STATUS_PAID)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
@@ -852,16 +855,11 @@ class AccountController extends AbstractController
|
|||||||
$lastName = trim($request->request->getString('last_name'));
|
$lastName = trim($request->request->getString('last_name'));
|
||||||
$email = trim($request->request->getString('email'));
|
$email = trim($request->request->getString('email'));
|
||||||
$redirectResponse = $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId(), 'tab' => 'invitations']);
|
$redirectResponse = $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId(), 'tab' => 'invitations']);
|
||||||
|
|
||||||
if ('' === $firstName || '' === $lastName || '' === $email) {
|
|
||||||
$this->addFlash('error', 'Tous les champs sont requis.');
|
|
||||||
|
|
||||||
return $redirectResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
$categories = $em->getRepository(Category::class)->findBy(['event' => $event], ['position' => 'ASC']);
|
$categories = $em->getRepository(Category::class)->findBy(['event' => $event], ['position' => 'ASC']);
|
||||||
if (empty($categories)) {
|
|
||||||
$this->addFlash('error', 'Creez au moins une categorie avant de generer une accreditation.');
|
$missingFields = '' === $firstName || '' === $lastName || '' === $email;
|
||||||
|
if ($missingFields || empty($categories)) {
|
||||||
|
$this->addFlash('error', $missingFields ? 'Tous les champs sont requis.' : 'Creez au moins une categorie avant de generer une accreditation.');
|
||||||
|
|
||||||
return $redirectResponse;
|
return $redirectResponse;
|
||||||
}
|
}
|
||||||
@@ -912,7 +910,6 @@ class AccountController extends AbstractController
|
|||||||
|
|
||||||
$billetOrderService->generateAndSendTickets($order);
|
$billetOrderService->generateAndSendTickets($order);
|
||||||
|
|
||||||
$label = 'staff' === $accreditationType ? 'Staff' : 'Exposant';
|
|
||||||
$this->addFlash('success', 'Accreditation '.$label.' envoyee a '.$order->getEmail().'.');
|
$this->addFlash('success', 'Accreditation '.$label.' envoyee a '.$order->getEmail().'.');
|
||||||
|
|
||||||
return $redirectResponse;
|
return $redirectResponse;
|
||||||
@@ -954,7 +951,7 @@ class AccountController extends AbstractController
|
|||||||
$pdf = $billetOrderService->generatePdf($ticket);
|
$pdf = $billetOrderService->generatePdf($ticket);
|
||||||
|
|
||||||
return new Response($pdf, 200, [
|
return new Response($pdf, 200, [
|
||||||
'Content-Type' => 'application/pdf',
|
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||||
'Content-Disposition' => 'inline; filename="'.$ticket->getReference().'.pdf"',
|
'Content-Disposition' => 'inline; filename="'.$ticket->getReference().'.pdf"',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -1010,16 +1007,8 @@ class AccountController extends AbstractController
|
|||||||
$categoryIds = array_map('intval', $request->request->all('categories'));
|
$categoryIds = array_map('intval', $request->request->all('categories'));
|
||||||
$billetIds = array_map('intval', $request->request->all('billets'));
|
$billetIds = array_map('intval', $request->request->all('billets'));
|
||||||
|
|
||||||
$categories = [];
|
$categories = $categoryIds ? $em->getRepository(Category::class)->findBy(['id' => $categoryIds, 'event' => $event]) : [];
|
||||||
if ($categoryIds) {
|
$billets = $billetIds ? array_filter($em->getRepository(Billet::class)->findBy(['id' => $billetIds]), fn (Billet $b) => $b->getCategory()->getEvent()->getId() === $event->getId()) : [];
|
||||||
$categories = $em->getRepository(Category::class)->findBy(['id' => $categoryIds, 'event' => $event]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$billets = [];
|
|
||||||
if ($billetIds) {
|
|
||||||
$billets = $em->getRepository(Billet::class)->findBy(['id' => $billetIds]);
|
|
||||||
$billets = array_filter($billets, fn (Billet $b) => $b->getCategory()->getEvent()->getId() === $event->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($categories) && empty($billets)) {
|
if (empty($categories) && empty($billets)) {
|
||||||
$this->addFlash('error', 'Selectionnez au moins une categorie ou un billet.');
|
$this->addFlash('error', 'Selectionnez au moins une categorie ou un billet.');
|
||||||
@@ -1027,83 +1016,11 @@ class AccountController extends AbstractController
|
|||||||
return $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId(), 'tab' => 'attestation']);
|
return $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId(), 'tab' => 'attestation']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$allBilletIds = [];
|
[$billets, $allBilletIds] = $this->collectAttestationBillets($billets, $categories, $em);
|
||||||
foreach ($billets as $b) {
|
[$billetLines, $totalSold] = $this->buildAttestationStats($billets, $allBilletIds, $em);
|
||||||
$allBilletIds[] = $b->getId();
|
$ticketDetails = $this->buildAttestationTicketDetails($allBilletIds, $em);
|
||||||
}
|
|
||||||
foreach ($categories as $cat) {
|
|
||||||
$catBillets = $em->getRepository(Billet::class)->findBy(['category' => $cat]);
|
|
||||||
foreach ($catBillets as $b) {
|
|
||||||
if (!\in_array($b->getId(), $allBilletIds, true)) {
|
|
||||||
$allBilletIds[] = $b->getId();
|
|
||||||
$billets[] = $b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$soldCounts = [];
|
|
||||||
$revenueCounts = [];
|
|
||||||
if ($allBilletIds) {
|
|
||||||
$rows = $em->createQueryBuilder()
|
|
||||||
->select('IDENTITY(bo.billet) AS billetId, COUNT(bo.id) AS cnt, SUM(bo.unitPriceHT) AS revenue')
|
|
||||||
->from(BilletOrder::class, 'bo')
|
|
||||||
->join('bo.billetBuyer', 'bb')
|
|
||||||
->where('bo.billet IN (:ids)')
|
|
||||||
->andWhere('bb.isInvitation = false OR bb.isInvitation IS NULL')
|
|
||||||
->setParameter('ids', $allBilletIds)
|
|
||||||
->groupBy('bo.billet')
|
|
||||||
->getQuery()
|
|
||||||
->getArrayResult();
|
|
||||||
foreach ($rows as $row) {
|
|
||||||
$soldCounts[(int) $row['billetId']] = (int) $row['cnt'];
|
|
||||||
$revenueCounts[(int) $row['billetId']] = (int) $row['revenue'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$billetLines = [];
|
|
||||||
$totalSold = 0;
|
|
||||||
$totalRevenue = 0;
|
|
||||||
foreach ($billets as $b) {
|
|
||||||
$sold = $soldCounts[$b->getId()] ?? 0;
|
|
||||||
$revenue = $revenueCounts[$b->getId()] ?? 0;
|
|
||||||
$billetLines[] = [
|
|
||||||
'category' => $b->getCategory()->getName(),
|
|
||||||
'name' => $b->getName(),
|
|
||||||
'priceHT' => $b->getPriceHTDecimal(),
|
|
||||||
'sold' => $sold,
|
|
||||||
'revenue' => $revenue / 100,
|
|
||||||
];
|
|
||||||
$totalSold += $sold;
|
|
||||||
$totalRevenue += $revenue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ticketDetails = [];
|
|
||||||
if ($allBilletIds) {
|
|
||||||
$tickets = $em->createQueryBuilder()
|
|
||||||
->select('t', 'bb')
|
|
||||||
->from(BilletOrder::class, 't')
|
|
||||||
->join('t.billetBuyer', 'bb')
|
|
||||||
->where('t.billet IN (:ids)')
|
|
||||||
->andWhere('bb.isInvitation = false OR bb.isInvitation IS NULL')
|
|
||||||
->setParameter('ids', $allBilletIds)
|
|
||||||
->orderBy('t.createdAt', 'ASC')
|
|
||||||
->getQuery()
|
|
||||||
->getResult();
|
|
||||||
|
|
||||||
foreach ($tickets as $t) {
|
|
||||||
$ticketDetails[] = [
|
|
||||||
'reference' => $t->getReference(),
|
|
||||||
'securityKey' => $t->getSecurityKey(),
|
|
||||||
'billetName' => $t->getBilletName(),
|
|
||||||
'orderNumber' => $t->getBilletBuyer()->getOrderNumber(),
|
|
||||||
'buyerName' => $t->getBilletBuyer()->getFirstName().' '.$t->getBilletBuyer()->getLastName(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$mode = $request->request->getString('mode', 'detail');
|
|
||||||
$isSimple = 'simple' === $mode;
|
|
||||||
|
|
||||||
|
$isSimple = 'simple' === $request->request->getString('mode', 'detail');
|
||||||
$generatedAt = new \DateTimeImmutable();
|
$generatedAt = new \DateTimeImmutable();
|
||||||
$selectedCategoryNames = array_map(fn ($c) => $c->getName(), $categories);
|
$selectedCategoryNames = array_map(fn ($c) => $c->getName(), $categories);
|
||||||
|
|
||||||
@@ -1165,7 +1082,7 @@ class AccountController extends AbstractController
|
|||||||
$dompdf->render();
|
$dompdf->render();
|
||||||
|
|
||||||
return new Response($dompdf->output(), 200, [
|
return new Response($dompdf->output(), 200, [
|
||||||
'Content-Type' => 'application/pdf',
|
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||||
'Content-Disposition' => 'inline; filename="attestation_'.$event->getSlug().'_'.date('Y-m-d').'.pdf"',
|
'Content-Disposition' => 'inline; filename="attestation_'.$event->getSlug().'_'.date('Y-m-d').'.pdf"',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -1469,7 +1386,7 @@ class AccountController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Response($pdfService->generate($payout), 200, [
|
return new Response($pdfService->generate($payout), 200, [
|
||||||
'Content-Type' => 'application/pdf',
|
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||||
'Content-Disposition' => 'inline; filename="attestation_'.$payout->getStripePayoutId().'.pdf"',
|
'Content-Disposition' => 'inline; filename="attestation_'.$payout->getStripePayoutId().'.pdf"',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -1525,6 +1442,103 @@ class AccountController extends AbstractController
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<Billet> $billets
|
||||||
|
* @param list<Category> $categories
|
||||||
|
*
|
||||||
|
* @return array{list<Billet>, list<int>}
|
||||||
|
*/
|
||||||
|
private function collectAttestationBillets(array $billets, array $categories, EntityManagerInterface $em): array
|
||||||
|
{
|
||||||
|
$allBilletIds = array_map(fn (Billet $b) => $b->getId(), $billets);
|
||||||
|
|
||||||
|
foreach ($categories as $cat) {
|
||||||
|
foreach ($em->getRepository(Billet::class)->findBy(['category' => $cat]) as $b) {
|
||||||
|
if (!\in_array($b->getId(), $allBilletIds, true)) {
|
||||||
|
$allBilletIds[] = $b->getId();
|
||||||
|
$billets[] = $b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$billets, $allBilletIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<Billet> $billets
|
||||||
|
* @param list<int> $allBilletIds
|
||||||
|
*
|
||||||
|
* @return array{list<array<string, mixed>>, int}
|
||||||
|
*/
|
||||||
|
private function buildAttestationStats(array $billets, array $allBilletIds, EntityManagerInterface $em): array
|
||||||
|
{
|
||||||
|
$soldCounts = [];
|
||||||
|
if ($allBilletIds) {
|
||||||
|
$rows = $em->createQueryBuilder()
|
||||||
|
->select('IDENTITY(bo.billet) AS billetId, COUNT(bo.id) AS cnt')
|
||||||
|
->from(BilletOrder::class, 'bo')
|
||||||
|
->join('bo.billetBuyer', 'bb')
|
||||||
|
->where('bo.billet IN (:ids)')
|
||||||
|
->andWhere(self::DQL_BB_EXCLUDE_INVITATIONS)
|
||||||
|
->setParameter('ids', $allBilletIds)
|
||||||
|
->groupBy('bo.billet')
|
||||||
|
->getQuery()
|
||||||
|
->getArrayResult();
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$soldCounts[(int) $row['billetId']] = (int) $row['cnt'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$billetLines = [];
|
||||||
|
$totalSold = 0;
|
||||||
|
foreach ($billets as $b) {
|
||||||
|
$sold = $soldCounts[$b->getId()] ?? 0;
|
||||||
|
$billetLines[] = [
|
||||||
|
'category' => $b->getCategory()->getName(),
|
||||||
|
'name' => $b->getName(),
|
||||||
|
'sold' => $sold,
|
||||||
|
];
|
||||||
|
$totalSold += $sold;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$billetLines, $totalSold];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<int> $allBilletIds
|
||||||
|
*
|
||||||
|
* @return list<array<string, mixed>>
|
||||||
|
*/
|
||||||
|
private function buildAttestationTicketDetails(array $allBilletIds, EntityManagerInterface $em): array
|
||||||
|
{
|
||||||
|
if (!$allBilletIds) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tickets = $em->createQueryBuilder()
|
||||||
|
->select('t', 'bb')
|
||||||
|
->from(BilletOrder::class, 't')
|
||||||
|
->join('t.billetBuyer', 'bb')
|
||||||
|
->where('t.billet IN (:ids)')
|
||||||
|
->andWhere(self::DQL_BB_EXCLUDE_INVITATIONS)
|
||||||
|
->setParameter('ids', $allBilletIds)
|
||||||
|
->orderBy('t.createdAt', 'ASC')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$details = [];
|
||||||
|
foreach ($tickets as $t) {
|
||||||
|
$details[] = [
|
||||||
|
'reference' => $t->getReference(),
|
||||||
|
'billetName' => $t->getBilletName(),
|
||||||
|
'orderNumber' => $t->getBilletBuyer()->getOrderNumber(),
|
||||||
|
'buyerName' => $t->getBilletBuyer()->getFirstName().' '.$t->getBilletBuyer()->getLastName(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $details;
|
||||||
|
}
|
||||||
|
|
||||||
private function requireEventOwnership(Event $event): User
|
private function requireEventOwnership(Event $event): User
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
@@ -1637,7 +1651,7 @@ class AccountController extends AbstractController
|
|||||||
$filename = sprintf('recap_%04d_%02d.pdf', $year, $month);
|
$filename = sprintf('recap_%04d_%02d.pdf', $year, $month);
|
||||||
|
|
||||||
return new Response($pdf, 200, [
|
return new Response($pdf, 200, [
|
||||||
'Content-Type' => 'application/pdf',
|
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||||
'Content-Disposition' => 'inline; filename="'.$filename.'"',
|
'Content-Disposition' => 'inline; filename="'.$filename.'"',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -1711,7 +1725,7 @@ class AccountController extends AbstractController
|
|||||||
->from(BilletBuyer::class, 'o')
|
->from(BilletBuyer::class, 'o')
|
||||||
->join('o.event', 'e')
|
->join('o.event', 'e')
|
||||||
->where('e.account = :user')
|
->where('e.account = :user')
|
||||||
->andWhere('o.isInvitation = false OR o.isInvitation IS NULL')
|
->andWhere(self::DQL_EXCLUDE_INVITATIONS)
|
||||||
->setParameter('user', $user)
|
->setParameter('user', $user)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult();
|
->getResult();
|
||||||
|
|||||||
Reference in New Issue
Block a user