src/Service/Notification.php line 81

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Historique;
  4. use App\Entity\InfosSuivi;
  5. use App\Entity\Lot;
  6. use App\Entity\Programme;
  7. use App\Entity\Prospect;
  8. use App\Entity\Impression;
  9. use App\Entity\Utilisateur;
  10. use App\Repository\ProspectRepository;
  11. use Symfony\Component\Mime\Email;
  12. use Symfony\Component\Mime\Address;
  13. use App\Repository\UtilisateurRepository;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Doctrine\Persistence\ManagerRegistry;
  16. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  17. use Symfony\Component\HttpFoundation\Cookie;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\Mailer\MailerInterface;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. use Symfony\Component\DependencyInjection\ContainerInterface;
  23. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  24. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  25. class Notification
  26. {
  27.     protected $doctrine;
  28.     protected $container;
  29.     protected $mailer;
  30.     protected $utilisateurRepository;
  31.     protected $prospectRepository;
  32.     protected $router;
  33.     private $creationPdf;
  34.     private $em;
  35.     public function __construct(ContainerInterface $containerManagerRegistry $doctrineMailerInterface $mailerUtilisateurRepository $utilisateurRepositoryProspectRepository $prospectRepositoryUrlGeneratorInterface $routerCreationPdf $creationPdfEntityManagerInterface $em)
  36.     {
  37.         $this->container $container;
  38.         $this->doctrine $doctrine;
  39.         $this->mailer $mailer;
  40.         $this->utilisateurRepository $utilisateurRepository;
  41.         $this->prospectRepository $prospectRepository;
  42.         $this->router $router;
  43.         $this->creationPdf $creationPdf;
  44.         $this->em $em;
  45.     }
  46.     public function alertInterne(Prospect $prospectImpression $impressionLot $lotUtilisateurRepository $utilisateurRepository)
  47.     {
  48.         $utilisateurs $utilisateurRepository->findBy( ['notification' => true]);
  49.         $destinataires = [];
  50.         foreach($utilisateurs as $utilisateur){
  51.             $destinataires[] = new Address($utilisateur->getEmail());
  52.         }
  53.         $email = (new TemplatedEmail())
  54.             ->from(new Address('mailer@zada.ai''Élise Bala'))
  55.             ->replyTo($prospect->getEmprunteurEmail())
  56.             ->to(...$destinataires)
  57.             ->subject($prospect->getEntreprise() . ' : nouveau retour de prospect')
  58.             ->htmlTemplate('emails/email_impression.html.twig')
  59.             ->context([
  60.                 'prospect' => $prospect,
  61.                 'impression' => $impression,
  62.                 'lot' => $lot
  63.             ])
  64.         ;
  65.         try {
  66.             $this->mailer->send($email);
  67.             return true;
  68.         } catch (TransportExceptionInterface $e) {
  69.             return false;
  70.         }
  71.     }
  72.     public function alertVisite(Prospect $prospectUtilisateurRepository $utilisateurRepositorystring $senderEmailHistorique $lastHistorique)
  73.     {
  74.         $existingInfosSuivi $this->em->getRepository(InfosSuivi::class)->findOneBy([
  75.             'historique' => $lastHistorique,
  76.             'type' => 'visite'
  77.         ]);
  78.         if ($existingInfosSuivi !== null) {
  79.             return false;
  80.         }
  81.         $SUPERADMINs $utilisateurRepository->createQueryBuilder('u')
  82.             ->where('u.email LIKE :email')
  83.             ->andWhere('u.notification = true')
  84.             ->setParameters(['email' => $senderEmail])
  85.             ->getQuery()
  86.             ->getResult();
  87.         $destinataires = [];
  88.         foreach ($SUPERADMINs as $SUPERADMIN) {
  89.             $destinataires[] = new Address($SUPERADMIN->getEmail());
  90.         }
  91.         $destinataires array_unique($destinatairesSORT_REGULAR);
  92.         $email = (new TemplatedEmail())
  93.             ->replyTo($prospect->getEmprunteurEmail())
  94.             ->to(...$destinataires)
  95.             ->subject($prospect->getEntreprise() . ' : nouvelle visite')
  96.             ->htmlTemplate('emails/email_visite.html.twig')
  97.             ->context([
  98.                 'prospect' => $prospect,
  99.                 'lastHistorique' => $lastHistorique
  100.             ]);
  101.         $email->from(new Address('mailer@zada.ai''LK1'));
  102.         $email->getHeaders()->addTextHeader('X-Transport''main');
  103.         $infoSuivi = new InfosSuivi();
  104.         $infoSuivi->setUtilisateur($prospect->getAuteur());
  105.         $infoSuivi->addProspect($prospect);
  106.         $infoSuivi->setHistorique($lastHistorique);
  107.         $infoSuivi->setType('visite');
  108.         $infoSuivi->setDescription('[prospect] a [visite] son espace public.');
  109.         $infoSuivi->setDate(new \DateTime());
  110.         $infoSuivi->setLu(false);
  111.         $this->em->persist($infoSuivi);
  112.         $this->em->flush();
  113.         try {
  114.             $this->mailer->send($email);
  115.             return true;
  116.         } catch (TransportExceptionInterface $e) {
  117.             return false;
  118.         }
  119.     }
  120.     public function alertProspect(Prospect $prospectRequest $request)
  121.     {
  122.         $subject $request->request->get('_mail_subject');
  123.         $message $request->request->get('_mail_message');
  124.         $addCopy $request->request->get('_mail_copy');
  125.         if (isset($addCopy)) {
  126.             $emailCopy $prospect->getCoEmprunteurEmail();
  127.         }
  128.         /** @var Utilisateur $user */
  129.         $user $this->container->get('security.token_storage')->getToken()->getUser();
  130.         $emailUser $user->getEmail();
  131.         $smtpEmail       $user->getSmtpEmail();
  132.         $smtpPassword    $user->getSmtpPassword();
  133.         $smtpDisplayName $user->getSmtpDisplayName();
  134.         if (!$smtpEmail || !$smtpPassword) {
  135.             return 'Aucun SMTP configuré pour votre compte. Veuillez renseigner vos paramètres SMTP dans votre profil utilisateur.';
  136.         }
  137.         /** @var \Twig\Environment $twig */
  138.         $twig $this->container->get('twig');
  139.         $html $twig->render('emails/email_layout.html.twig', [
  140.             'prospect' => $prospect,
  141.             'message'  => $message,
  142.         ]);
  143.         $email = (new Email())
  144.             ->to($prospect->getEmprunteurEmail())
  145.             ->replyTo($emailUser)
  146.             ->subject($subject)
  147.             ->from(new Address(
  148.                 $smtpEmail,
  149.                 $smtpDisplayName ?: $smtpEmail
  150.             ))
  151.             ->html($html)
  152.         ;
  153.         if (isset($emailCopy)) {
  154.             $email->addCc($emailCopy);
  155.         }
  156.         $dsn sprintf(
  157.             'smtp://%s:%s@smtp.office365.com:587/?allow_peer=0',
  158.             rawurlencode($smtpEmail),
  159.             $smtpPassword
  160.         );
  161.         $transport     = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
  162.         $dynamicMailer = new \Symfony\Component\Mailer\Mailer($transport);
  163.         try {
  164.             $dynamicMailer->send($email);
  165.             return true;
  166.         } catch (TransportExceptionInterface $e) {
  167.             return 'Erreur envoi SMTP : ' $e->getMessage();
  168.         }
  169.     }
  170.     public function alertProspectATraiter(Prospect $prospectUtilisateur $negociateur): bool
  171.     {
  172.         if (!$prospect->getEmprunteurEmail()) {
  173.             return false;
  174.         }
  175.         $subject sprintf('%s - Demande confirmée : un expert vous contacte rapidement'$prospect->getEntreprise());
  176.         $message sprintf(
  177.             "Suite à votre demande d'informations, un expert %s va vous rappeler dans les plus brefs délais pour échanger sur votre projet.\nDans l'intervalle, vous pouvez également nous proposer un créneau horaire à votre convenance.",
  178.             $prospect->getEntreprise()
  179.         );
  180.         // Utilisation du NOUVEAU TEMPLATE email_atraiter.html.twig
  181.         $email = (new TemplatedEmail())
  182.             ->to($prospect->getEmprunteurEmail())
  183.             ->subject($subject)
  184.             ->htmlTemplate('emails/email_atraiter.html.twig')
  185.             ->context([
  186.                 'prospect' => $prospect,
  187.                 'message' => nl2br($message),
  188.             ]);
  189.         $email->from(new Address('mailer@zada.ai''LK1 Immobilier'));
  190.         $email->getHeaders()->addTextHeader('X-Transport''main');
  191.         try {
  192.             $this->mailer->send($email);
  193.             return true;
  194.         } catch (TransportExceptionInterface $e) {
  195.             return false;
  196.         }
  197.     }
  198.     public function alertAuteurProspect(int $prospectIdint $auteurIdUtilisateur $userConnected)
  199.     {
  200.         $auteur $this->utilisateurRepository->find($auteurId);
  201.         $prospect $this->prospectRepository->find($prospectId);
  202.         if (!$auteur || !$prospect) {
  203.             return false;
  204.         }
  205.         $pdfPath $this->creationPdf->createPDF($prospect'/''file');
  206.         $email = (new TemplatedEmail())
  207.             ->from(new Address('mailer@zada.ai''LK1'))
  208.             ->to($auteur->getEmail())
  209.             ->subject($prospect->getEntreprise() . ' : nouveau contact à traiter')
  210.             ->htmlTemplate('emails/email_nouveau_contact.html.twig')
  211.             ->context([
  212.                 'prospect' => $prospect,
  213.                 'auteur' => $auteur,
  214.             ])
  215.             ->attachFromPath($pdfPath);
  216.         try {
  217.             $this->mailer->send($email);
  218.             if ($pdfPath) {
  219.                 if (is_file($pdfPath)) {
  220.                     unlink($pdfPath);
  221.                 }
  222.             }
  223.             $this->addNotificationForAdmins($prospect$auteur$userConnected);
  224.     
  225.             return true;
  226.         } catch (TransportExceptionInterface $e) {
  227.             if ($pdfPath) {
  228.                 if (is_file($pdfPath)) {
  229.                     unlink($pdfPath);
  230.                 }
  231.             }
  232.             return false;
  233.         }
  234.     }
  235.     /**
  236.      * Méthode pour notifier les SUPERADMIN d'une demande de suppression de programme
  237.      */
  238.     public function alertDemandeSuppression(Programme $programmeUtilisateur $userConnected)
  239.     {
  240.         $entreprise $programme->getEntreprise();
  241.         if (!$entreprise) {
  242.             return false;
  243.         }
  244.         $superAdmins $this->utilisateurRepository->createQueryBuilder('u')
  245.             ->where('u.entreprise = :entreprise')
  246.             ->andWhere('u.roles LIKE :roleSuperAdmin')
  247.             ->setParameter('entreprise'$entreprise)
  248.             ->setParameter('roleSuperAdmin''%ROLE_SUPERADMIN%')
  249.             ->getQuery()
  250.             ->getResult();
  251.         foreach ($superAdmins as $admin) {
  252.             $infoSuivi = new InfosSuivi();
  253.             $infoSuivi->setUtilisateur($admin);
  254.             $infoSuivi->setType('suppr');
  255.             $infoSuivi->setDescription('[user] a fait une [demande de suppression] pour le programme [programme].');
  256.             $infoSuivi->setDate(new \DateTime());
  257.             $infoSuivi->setLu(false);
  258.             $infoSuivi->setConnectedUser($userConnected);
  259.             $infoSuivi->setProgramme($programme);
  260.             $this->em->persist($infoSuivi);
  261.         }
  262.         $this->em->flush();
  263.         return true;
  264.     }
  265.     public function alertRapportATraiter(array $admins, array $prospects, \DateTimeInterface $start, \DateTimeInterface $end)
  266.     {
  267.         if (empty($admins)) {
  268.             return array(
  269.                 'success' => false,
  270.                 'errors' => array('Aucun admin éligible pour recevoir le rapport.')
  271.             );
  272.         }
  273.         // Préparer les données structurées pour le template
  274.         $prospectData = array();
  275.         foreach ($prospects as $prospect) {
  276.             /** @var \App\Entity\Prospect $prospect */
  277.             $hasClicked $prospect->getDateCliqueATraiter()
  278.                 && $prospect->getDateCliqueATraiter() >= $start
  279.                 && $prospect->getDateCliqueATraiter() <= $end;
  280.             $negociateur $prospect->getAuteur()
  281.                 ? trim($prospect->getAuteur()->getPrenom() . ' ' $prospect->getAuteur()->getNom())
  282.                 : 'Non assigné';
  283.             $client trim($prospect->getEmprunteurNom() . ' ' $prospect->getEmprunteurPrenom());
  284.             $prospectData[] = array(
  285.                 'id' => $prospect->getId(),
  286.                 'client' => $client,
  287.                 'negociateur' => $negociateur,
  288.                 'hasClicked' => $hasClicked,
  289.                 'dateCreation' => $prospect->getDateDerniereModification()
  290.                     ? $prospect->getDateDerniereModification()->format('d/m/Y à H\hi')
  291.                     : 'N/A'
  292.             );
  293.         }
  294.         // User connecté uniquement pour le reply-to (pas pour le SMTP)
  295.         $emailUser null;
  296.         if ($this->container->has('security.token_storage')
  297.             && $this->container->get('security.token_storage')->getToken()
  298.         ) {
  299.             $user $this->container->get('security.token_storage')->getToken()->getUser();
  300.             if ($user instanceof Utilisateur && $user->getEmail()) {
  301.                 $emailUser $user->getEmail();
  302.             }
  303.         }
  304.         // Rendu du template Twig
  305.         /** @var \Twig\Environment $twig */
  306.         $twig $this->container->get('twig');
  307.         $html $twig->render('emails/rapport.html.twig', [
  308.             'prospects' => $prospectData,
  309.             'start' => $start,
  310.             'end' => $end,
  311.             'totalProspects' => count($prospectData),
  312.             'prospectsCliques' => count(array_filter($prospectData, function($p) { return $p['hasClicked']; })),
  313.             'prospectsNonCliques' => count(array_filter($prospectData, function($p) { return !$p['hasClicked']; }))
  314.         ]);
  315.         $success false;
  316.         $errors  = array();
  317.         foreach ($admins as $admin) {
  318.             if (!method_exists($admin'getEmail') || !$admin->getEmail()) {
  319.                 $errors[] = 'Admin sans email valide.';
  320.                 continue;
  321.             }
  322.             $email = (new Email())
  323.                 ->from(new Address('mailer@zada.ai''LK1'))
  324.                 ->to($admin->getEmail())
  325.                 ->subject('Rapport quotidien - Prospects A TRAITER (depuis ' $start->format('d/m/Y à H\hi') . ')')
  326.                 ->html($html);
  327.             if ($emailUser) {
  328.                 $email->replyTo($emailUser);
  329.             }
  330.             // Utilise le transport par défaut "main"
  331.             $email->getHeaders()->addTextHeader('X-Transport''main');
  332.             try {
  333.                 $this->mailer->send($email);
  334.                 $success true;
  335.             } catch (TransportExceptionInterface $e) {
  336.                 $errors[] = sprintf(
  337.                     'Erreur pour %s : %s',
  338.                     $admin->getEmail(),
  339.                     $e->getMessage()
  340.                 );
  341.             }
  342.         }
  343.         return array(
  344.             'success' => $success,
  345.             'errors'  => $errors,
  346.         );
  347.     }
  348.     private function addNotificationForAdmins(Prospect $prospect, ?Utilisateur $auteurUtilisateur $userConnected)
  349.     {
  350.         $entreprise $auteur $auteur->getEntreprise() : null;
  351.         $queryBuilder $this->utilisateurRepository->createQueryBuilder('u');
  352.     
  353.         if ($entreprise) {
  354.             $queryBuilder->where('u.entreprise = :entreprise')
  355.                 ->setParameter('entreprise'$entreprise);
  356.         }
  357.     
  358.         $queryBuilder->andWhere(
  359.             $queryBuilder->expr()->orX(
  360.                 $queryBuilder->expr()->like('u.roles'':rolesAdmin'),
  361.                 $queryBuilder->expr()->like('u.roles'':rolesSuperAdmin')
  362.             )
  363.         )
  364.         ->setParameter('rolesAdmin''%ROLE_ADMIN%')
  365.         ->setParameter('rolesSuperAdmin''%ROLE_SUPERADMIN%');
  366.     
  367.         if (in_array('ROLE_COMMERCIAL'$auteur->getRoles())) {
  368.             $queryBuilder->orWhere('u.roles LIKE :rolesDirecteur')
  369.                 ->setParameter('rolesDirecteur''%ROLE_DIRECTEUR%');
  370.         }
  371.         if (in_array('ROLE_PARTENAIRE'$auteur->getRoles())) {
  372.             $queryBuilder->orWhere('u.roles LIKE :rolesResponsable')
  373.                 ->setParameter('rolesResponsable''%ROLE_RESPONSABLE%');
  374.         }
  375.         $admins $queryBuilder->getQuery()->getResult();
  376.     
  377.         foreach ($admins as $admin) {
  378.             $infoSuivi = new InfosSuivi();
  379.             $infoSuivi->setUtilisateur($admin);
  380.             $infoSuivi->addProspect($prospect);
  381.             $infoSuivi->setType('client');
  382.             $infoSuivi->setDescription('Le client [prospect] a été attribué à [user] par [connectedUser]');
  383.             $infoSuivi->setDate(new \DateTime());
  384.             $infoSuivi->setLu(false);
  385.             $infoSuivi->setAuteur($auteur);
  386.             $infoSuivi->setConnectedUser($userConnected);
  387.     
  388.             $this->em->persist($infoSuivi);
  389.         }
  390.     
  391.         $this->em->flush();
  392.     }
  393. }