← Back
Editing: AdresseController.php
<?php namespace App\Controller; use App\Entity\Adresse; use App\Entity\AgencyPrestataire; use App\Entity\Item; use App\Entity\Note; use App\Entity\User; use App\Entity\UserAddress; use App\Event\AddressCreateEvent; use App\Form\AddressAssignementsType; use App\Form\AdresseType; use App\Notation\Render\NoteColorator; use App\Repository\AdresseRepository; use App\Repository\ControleRepository; use App\Repository\HistoriqueAlerteRepository; use App\Repository\PrestataireRepository; use App\Repository\ReportRepository; use App\Repository\ThematicRepository; use App\Repository\UserRepository; use App\Service\ElevatorBreakdownService; use App\Service\NotificationService; use App\Service\SolutionService; use App\Service\UserService; use App\Session\Filter\Role\ManagerSessionFilters; use App\Session\Filter\SessionFiltersContainer; use App\Session\Filter\ValueObject\DateRange; use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; use Dompdf\Dompdf; use Dompdf\Options; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; #[Route(path: '/adresse')] class AdresseController extends AbstractController { public function __construct( private readonly NoteColorator $noteColorator ) { } #[Route(path: '/carte', name: 'address_map', methods: ['GET'])] public function map( Request $request, SolutionService $solutionService, AdresseRepository $adresseRepository, ReportRepository $reportRepository, ): Response { $sort = $request->get('perfSort', 'desc'); $addressQuery = $adresseRepository->getQueryByManager( $this->getUser() ) ->select('a as addr') ->addSelect('COUNT(c.id) as cnt') ->addSelect('AVG(c.averageNote) as avgNote') ->groupBy('a') ->orderBy('cnt', $sort); $reports = []; if ('clean-manager' === $solutionService->getCurrent()->getSlug()) { $reports = $reportRepository->getReportsForCart($this->getUser()); } return $this->render( 'adresse/carte.html.twig', [ 'addresses' => $addressQuery->getQuery()->getResult(), 'reports' => $reports, ], ); } #[Route(path: '/pannes-ascenseur.html', name: 'elevator_breakdown_history', methods: ['GET'])] public function elevatorBreakdownHistory( ElevatorBreakdownService $elevatorBreakdownService, ManagerSessionFilters $filters ): Response { return $this->render( 'adresse/elevator-breakdown-history.html.twig', [ 'historic' => $elevatorBreakdownService->groupBreakdownsByMonth( $this->getUser(), $filters->getDateRange()->getDateStart(), $filters->getDateRange()->getDateEnd() ), ] ); } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ #[Route(path: '/', name: 'adresse_index', requirements: ['_format' => 'html|pdf'], methods: ['GET'])] public function index( SolutionService $solutionService, ElevatorBreakdownService $breakdownService, UserService $userService, EntityManagerInterface $em ): Response { $users = $userService->getAgentsForCurrentSolution(); $prestataires = $em ->getRepository(AgencyPrestataire::class) ->getPrestatairesByManager($this->getUser()); $solutionName = $solutionService->getCurrent(); if ($this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { $adresses = $em->getRepository(Adresse::class)->getAll(); $params = [ 'adresses' => $adresses, 'ActualUser' => $this->getUser(), 'breakdownService' => $breakdownService, ]; } else { $adresses = $em->getRepository(Adresse::class)->getByManager($this->getUser()); $params = [ 'adresses' => $adresses, 'users' => $users, 'prestataires' => $prestataires, 'solutionName' => $solutionName, 'breakdownService' => $breakdownService, ]; } return $this->render('adresse/index.html.twig', $params); } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ #[Route(path: '/export/pdf', name: 'adresse_export_pdf_index', methods: ['GET'])] public function exportPdfIndex(AdresseRepository $adresseRepository): Response { /** @var User $user */ $user = $this->getUser(); if ($this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { $adresseList = $adresseRepository->findAll(); } else { $adresseList = $adresseRepository->findBy(['agency' => $user->getAgency()]); } // Configure Dompdf according to your needs $pdfOptions = new Options(); $pdfOptions->set('defaultFont', 'Arial'); // Instantiate Dompdf with our options $dompdf = new Dompdf($pdfOptions); $dompdf->set_option('isHtml5ParserEnabled', true); // Retrieve the HTML generated in our twig file $html = $this->renderView( 'export/pdf_adresse.html.twig', [ 'adresseList' => $adresseList, 'user' => $this->getUser(), ] ); // Load HTML to Dompdf $dompdf->loadHtml($html); // (Optional) Setup the paper size and orientation 'portrait' or 'landscape' $dompdf->setPaper('A4', 'landscape'); // Render the HTML as PDF $dompdf->render(); // Output the generated PDF to Browser (force download) $dompdf->stream( 'adresses.pdf', [ 'Attachment' => true, ] ); return new Response(); } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ #[Route(path: '/new', name: 'adresse_new', methods: ['GET', 'POST'])] public function new( Request $request, SolutionService $solutionService, EventDispatcherInterface $dispatcher ): Response { /** @var User $user */ $user = $this->getUser(); $adresse = new Adresse(); $options['authorization_checker'] = $this->container->get('security.authorization_checker'); $agency = $user->getAgency(); $adresse->setAscenseurIsActive(true); $adresse->setAgency($agency); $adresse->setManager($user); $options['agency'] = $agency; $options['solution'] = $solutionService->getCurrent(); $form = $this->createForm(AdresseType::class, $adresse, $options); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $dispatcher->dispatch(new AddressCreateEvent($adresse), AddressCreateEvent::NAME); return $this->redirectToRoute('adresse_index'); } return $this->render( 'adresse/new.html.twig', [ 'adresse' => $adresse, 'form' => $form->createView(), ] ); } #[Route(path: '/{id}', name: 'adresse_show', options: ['expose' => true], methods: ['GET'])] public function show(Adresse $adresse): Response { return $this->render( 'adresse/show.html.twig', [ 'adresse' => $adresse, ] ); } /** * @throws NonUniqueResultException * @throws \Exception */ #[Route(path: '/detail/{id}.html', name: 'adresse_detail', options: ['expose' => true], methods: ['GET'])] public function detail( Adresse $adresse, SessionFiltersContainer $sessionFiltersContainer, ThematicRepository $thematicRepository, EntityManagerInterface $em, ControleRepository $controleRepository ): Response { $filters = $sessionFiltersContainer->getCurrent(); $statsItem = $this->getStatsItem( $adresse, $em, $filters->getDateRange()->getDateStart(), $filters->getDateRange()->getDateEnd() ); $thematics = $thematicRepository->findForAddress($adresse); $avgNote = $controleRepository->getTotalAverageNoteByAddress($adresse); return $this->render( 'adresse/detail.html.twig', [ 'adresse' => $adresse, 'thematics' => $thematics, 'prestataire' => $adresse->getPrestataires()->first(), 'statsItem' => $statsItem, 'avgNote' => $avgNote['avgNote'] ?? 0, ] ); } /** * @throws \Exception */ public function averageNoteChart( Adresse $adresse, ControleRepository $controleRepository ): Response { $formatter = new \IntlDateFormatter('fr_FR', \IntlDateFormatter::TRADITIONAL, \IntlDateFormatter::TRADITIONAL); $formatter->setPattern('MMM yy'); $data = $controleRepository->getAverageNoteByAddress($adresse); $datas = []; foreach ($data as $note) { $date = new \DateTime($note['month'].'-01'); $datas[$formatter->format($date)] = $note['avgNote']; } return $this->render('adresse/_average_notes.html.twig', ['datas' => $datas]); } /** * @throws \Exception */ private function getStatsItem( Adresse $adresse, EntityManagerInterface $em, ?\DateTime $startDate = null, ?\DateTime $endDate = null ): array { $allItems = $em->getRepository(Item::class)->getAllWithZone($this->getUser()); $statsItem = $em->getRepository(Note::class)->averageNoteItemsByManager( manager: $this->getUser(), adresse: $adresse, options: [ 'dateRange' => new DateRange($startDate, $endDate), ] ); $diff = []; foreach ($allItems as $item) { $item['averageNote'] = 0; $add = true; foreach ($statsItem as $stat) { if ($item['itemId'] === $stat['itemId']) { $add = false; break; } } if ($add) { $diff[] = $item; } } $statsItem = array_merge($statsItem, $diff); $result = []; foreach ($statsItem as $stat) { $arr['item'] = $stat['item']; $arr['notationType'] = $stat['notationType']; $arr['averageNote'] = round($stat['averageNote'], 1); $arr['itemSubZone'] = null; $zone = $stat['zone']; if (str_contains($stat['zone'], 'PROPRETE')) { $zone = 'PROPRETE'; if (!str_contains($stat['zone'], 'AUTRES LOCAUX')) { $arr['itemSubZone'] = substr($stat['zone'], 10); } } /* @todo Refactoriser ce truc immonde */ $arr['colorCode'] = ($this->noteColorator)($arr['averageNote']); $arr['color'] = ($arr['averageNote'] >= 3.5) ? 'blue' : 'pink'; $arr['color'] = ('pink' == $arr['color'] && $arr['averageNote'] > 2) ? 'green' : $arr['color']; $arr['percentage'] = ($arr['averageNote'] / 5) * 100; $arr['itemId'] = $stat['itemId']; $result[$zone][] = $arr; } return $result; } /** * @throws NoResultException * @throws NonUniqueResultException */ public function notesAverage( Adresse $adresse, ControleRepository $controleRepository ): Response { $averageNote = round( $controleRepository->averageNoteByManager( $this->getUser(), $adresse ), 1 ); return $this->render('adresse/widgets/_show.html.twig', [ 'label' => 'Note moyenne', 'value' => number_format($averageNote, 2).'/5', ]); } public function controlesDone( Adresse $adresse, ManagerSessionFilters $sessionFilters ): Response { $criteria = Criteria::create() ->andWhere(Criteria::expr()->gte('dateRealisation', $sessionFilters->getDateRange()->getDateStart())) ->andWhere(Criteria::expr()->lte('dateRealisation', $sessionFilters->getDateRange()->getDateEnd())); return $this->render('adresse/widgets/_show.html.twig', [ 'label' => 'Contrôles', 'value' => count($adresse->getControles()->matching($criteria)), ]); } public function prestatairesAlerts( Adresse $adresse, HistoriqueAlerteRepository $historiqueAlerteRepository, ManagerSessionFilters $sessionFilters ): Response { $historiqueAlertes = $historiqueAlerteRepository->findByUser( $this->getUser(), $adresse ); $diff = $sessionFilters->getDateRange()->getDateEnd()->diff($sessionFilters->getDateRange()->getDateStart()); $months = 0; $label = 'Alertes'; if ($diff->y >= 1) { $months += ($diff->y * 12) + $diff->m; } if ($diff->m >= 1) { $months += $diff->m; } if ($months > 0) { $historiqueAlertes = number_format(count($historiqueAlertes) / $months, 1); } else { $historiqueAlertes = count($historiqueAlertes); } return $this->render( 'adresse/widgets/_show.html.twig', ['value' => number_format($historiqueAlertes, 2), 'label' => $label] ); } public function incidenceChart( Adresse $adresse, ControleRepository $controleRepository ): Response { $total = 0; $notes = $controleRepository->incidenceByAgenciesByMonth( agencies: [$this->getUser()->getAgency()->getId()], adresse: $adresse ); if (count($notes) > 0) { $total = array_reduce($notes, function ($carry, $item) { return $carry + $item['incidence']; }, 0) / count($notes); } $total *= 100; return $this->render( 'adresse/widgets/_show.html.twig', ['value' => number_format($total, 2).'%', 'label' => 'Taux d\'incidence'] ); } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ #[Route(path: '/{id}/edit', name: 'adresse_edit', methods: ['GET', 'POST'])] public function edit( Request $request, Adresse $adresse, SolutionService $solutionService, EntityManagerInterface $em ): Response { $options['authorization_checker'] = $this->container->get('security.authorization_checker'); $agency = $this->getUser()->getAgency(); $options['agency'] = $agency; $options['solution'] = $solutionService->getCurrent(); $form = $this->createForm(AdresseType::class, $adresse, $options); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em->flush(); return $this->redirectToRoute('adresse_index'); } return $this->render( 'adresse/edit.html.twig', [ 'adresse' => $adresse, 'form' => $form->createView(), ] ); } #[Route(path: '/edit', name: 'adresse_edit_controles', methods: ['POST'])] public function editControles( Request $request, UserRepository $userRepository, PrestataireRepository $prestataireRepository, AdresseRepository $adresseRepository, EntityManagerInterface $em ): Response { /** @var array $listAdresseId */ $listAdresseId = $request->request->all()['adresses']; $userId = $request->request->get('user'); $prestataireId = $request->request->get('provider'); if ('null' !== $userId) { $user = $userRepository->find($userId); } if ('null' !== $prestataireId) { $prestataire = $prestataireRepository->find($prestataireId); } if (0 !== count($listAdresseId)) { for ($i = 0; $i < count($listAdresseId); ++$i) { $adresseId = $listAdresseId[$i]; $adresse = $adresseRepository->find($adresseId); if ('null' !== $userId) { if (!$adresse->containsAgent($user)) { $adresse->clearUserAddresses(); $userAddress = new UserAddress(); $userAddress->setUser($user); $adresse->addUserAddress($userAddress); } } if ('null' !== $prestataireId) { foreach ($adresse->getPrestataires() as $tmp) { $adresse->removePrestataire($tmp); } $adresse->addPrestataire($prestataire); } $em->persist($adresse); } } $em->flush(); return new JsonResponse(['status' => 'OK']); } #[Route(path: '/{id}', name: 'adresse_delete', methods: ['POST', 'DELETE'])] public function delete(Request $request, Adresse $adresse, EntityManagerInterface $em): Response { if ($this->isCsrfTokenValid('delete'.$adresse->getId(), $request->request->get('_token'))) { $em->remove($adresse); $em->flush(); $this->addFlash('success', 'Cette adresse a bien été supprimée.'); } return $this->redirectToRoute('adresse_index'); } #[Route(path: '/adresse/{id}/active', name: 'adresse_active')] public function active(Adresse $adresse, EntityManagerInterface $em): RedirectResponse { $adresse->setStartDateInactive(new \DateTime('+50 year')); $em->persist($adresse); $em->flush(); $this->addFlash('success', 'Cette adresse a bien été activée.'); return $this->redirectToRoute('adresse_index'); } #[Route(path: '/adresse/{id}/unactive', name: 'adresse_unactive')] public function unactive(Adresse $adresse, EntityManagerInterface $em): RedirectResponse { $adresse->setStartDateInactive(new \DateTime()); $em->persist($adresse); $em->flush(); $this->addFlash('success', 'Cette adresse a bien été désactivée.'); return $this->redirectToRoute('adresse_index'); } #[Route(path: '/adresse/remind', name: 'address_remind')] public function sendReminder( Request $request, NotificationService $notificationService, AdresseRepository $adresseRepository ): JsonResponse { $addressesIds = $request->request->all()['addresses']; foreach ($addressesIds as $id) { $addr = $adresseRepository->find($id); $notificationService->sendReminder($addr); } $this->addFlash('success', 'Les agents ont bien été notifiés'); return new JsonResponse(['status' => 'OK']); } #[Route(path: '/assignement-form/{id}', name: 'assignement_form')] public function assignementForm(Adresse $address, Request $request, EntityManagerInterface $em): Response { $form = $this->createForm(AddressAssignementsType::class, $address); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em->persist($form->getData()); $em->flush(); $this->addFlash('success', 'Vos changements sur cette adresse ont bien été effectués'); } return $this->render( 'adresse/_assignement_form.html.twig', ['form' => $form->createView(), 'address' => $address] ); } }
Save File
Cancel