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 EVENT_BASE_URL = '/mon-compte/evenement/';
|
||||
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')]
|
||||
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')
|
||||
->join('bo.billetBuyer', 'bb')
|
||||
->where('bo.billet IN (:ids)')
|
||||
->andWhere('bb.isInvitation = false OR bb.isInvitation IS NULL')
|
||||
->andWhere(self::DQL_BB_EXCLUDE_INVITATIONS)
|
||||
->setParameter('ids', $billetIds)
|
||||
->groupBy('bo.billet')
|
||||
->getQuery()
|
||||
@@ -484,7 +487,7 @@ class AccountController extends AbstractController
|
||||
->leftJoin('o.items', 'i')
|
||||
->where('o.event = :event')
|
||||
->andWhere('o.status = :status')
|
||||
->andWhere('o.isInvitation = false OR o.isInvitation IS NULL')
|
||||
->andWhere(self::DQL_EXCLUDE_INVITATIONS)
|
||||
->setParameter('event', $event)
|
||||
->setParameter('status', BilletBuyer::STATUS_PAID)
|
||||
->getQuery()
|
||||
@@ -852,16 +855,11 @@ class AccountController extends AbstractController
|
||||
$lastName = trim($request->request->getString('last_name'));
|
||||
$email = trim($request->request->getString('email'));
|
||||
$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']);
|
||||
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;
|
||||
}
|
||||
@@ -912,7 +910,6 @@ class AccountController extends AbstractController
|
||||
|
||||
$billetOrderService->generateAndSendTickets($order);
|
||||
|
||||
$label = 'staff' === $accreditationType ? 'Staff' : 'Exposant';
|
||||
$this->addFlash('success', 'Accreditation '.$label.' envoyee a '.$order->getEmail().'.');
|
||||
|
||||
return $redirectResponse;
|
||||
@@ -954,7 +951,7 @@ class AccountController extends AbstractController
|
||||
$pdf = $billetOrderService->generatePdf($ticket);
|
||||
|
||||
return new Response($pdf, 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||
'Content-Disposition' => 'inline; filename="'.$ticket->getReference().'.pdf"',
|
||||
]);
|
||||
}
|
||||
@@ -1010,16 +1007,8 @@ class AccountController extends AbstractController
|
||||
$categoryIds = array_map('intval', $request->request->all('categories'));
|
||||
$billetIds = array_map('intval', $request->request->all('billets'));
|
||||
|
||||
$categories = [];
|
||||
if ($categoryIds) {
|
||||
$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());
|
||||
}
|
||||
$categories = $categoryIds ? $em->getRepository(Category::class)->findBy(['id' => $categoryIds, 'event' => $event]) : [];
|
||||
$billets = $billetIds ? array_filter($em->getRepository(Billet::class)->findBy(['id' => $billetIds]), fn (Billet $b) => $b->getCategory()->getEvent()->getId() === $event->getId()) : [];
|
||||
|
||||
if (empty($categories) && empty($billets)) {
|
||||
$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']);
|
||||
}
|
||||
|
||||
$allBilletIds = [];
|
||||
foreach ($billets as $b) {
|
||||
$allBilletIds[] = $b->getId();
|
||||
}
|
||||
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;
|
||||
[$billets, $allBilletIds] = $this->collectAttestationBillets($billets, $categories, $em);
|
||||
[$billetLines, $totalSold] = $this->buildAttestationStats($billets, $allBilletIds, $em);
|
||||
$ticketDetails = $this->buildAttestationTicketDetails($allBilletIds, $em);
|
||||
|
||||
$isSimple = 'simple' === $request->request->getString('mode', 'detail');
|
||||
$generatedAt = new \DateTimeImmutable();
|
||||
$selectedCategoryNames = array_map(fn ($c) => $c->getName(), $categories);
|
||||
|
||||
@@ -1165,7 +1082,7 @@ class AccountController extends AbstractController
|
||||
$dompdf->render();
|
||||
|
||||
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"',
|
||||
]);
|
||||
}
|
||||
@@ -1469,7 +1386,7 @@ class AccountController extends AbstractController
|
||||
}
|
||||
|
||||
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"',
|
||||
]);
|
||||
}
|
||||
@@ -1525,6 +1442,103 @@ class AccountController extends AbstractController
|
||||
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
|
||||
{
|
||||
/** @var User $user */
|
||||
@@ -1637,7 +1651,7 @@ class AccountController extends AbstractController
|
||||
$filename = sprintf('recap_%04d_%02d.pdf', $year, $month);
|
||||
|
||||
return new Response($pdf, 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Type' => self::CONTENT_TYPE_PDF,
|
||||
'Content-Disposition' => 'inline; filename="'.$filename.'"',
|
||||
]);
|
||||
}
|
||||
@@ -1711,7 +1725,7 @@ class AccountController extends AbstractController
|
||||
->from(BilletBuyer::class, 'o')
|
||||
->join('o.event', 'e')
|
||||
->where('e.account = :user')
|
||||
->andWhere('o.isInvitation = false OR o.isInvitation IS NULL')
|
||||
->andWhere(self::DQL_EXCLUDE_INVITATIONS)
|
||||
->setParameter('user', $user)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
Reference in New Issue
Block a user