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.         $SUPERADMINs $utilisateurRepository->createQueryBuilder('u')
  75.             ->where('u.email LIKE :email')
  76.             ->andWhere('u.notification = true')
  77.             ->setParameters(['email' => $senderEmail])
  78.             ->getQuery()
  79.             ->getResult();
  80.         $destinataires = [];
  81.         foreach ($SUPERADMINs as $SUPERADMIN) {
  82.             $destinataires[] = new Address($SUPERADMIN->getEmail());
  83.         }
  84.         $destinataires array_unique($destinatairesSORT_REGULAR);
  85.         $email = (new TemplatedEmail())
  86.             ->replyTo($prospect->getEmprunteurEmail())
  87.             ->to(...$destinataires)
  88.             ->subject($prospect->getEntreprise() . ' : nouvelle visite')
  89.             ->htmlTemplate('emails/email_visite.html.twig')
  90.             ->context([
  91.                 'prospect' => $prospect,
  92.                 'lastHistorique' => $lastHistorique
  93.             ]);
  94.         $email->from(new Address('mailer@zada.ai''LK1'));
  95.         $email->getHeaders()->addTextHeader('X-Transport''main');
  96.     
  97.         $infoSuivi = new InfosSuivi();
  98.         $infoSuivi->setUtilisateur($prospect->getAuteur());
  99.         $infoSuivi->addProspect($prospect);
  100.         $infoSuivi->setHistorique($lastHistorique);
  101.         $infoSuivi->setType('visite');
  102.         $infoSuivi->setDescription('[prospect] a [visite] son espace public.');
  103.         $infoSuivi->setDate(new \DateTime());
  104.         $infoSuivi->setLu(false);
  105.         $this->em->persist($infoSuivi);
  106.         $this->em->flush();
  107.         try {
  108.             $this->mailer->send($email);
  109.     
  110.             return true;
  111.         } catch (TransportExceptionInterface $e) {
  112.             return false;
  113.         }
  114.     }
  115.     public function alertProspect(Prospect $prospectRequest $request)
  116.     {
  117.         $subject $request->request->get('_mail_subject');
  118.         $message $request->request->get('_mail_message');
  119.         $addCopy $request->request->get('_mail_copy');
  120.         if (isset($addCopy)) {
  121.             $emailCopy $prospect->getCoEmprunteurEmail();
  122.         }
  123.         /** @var Utilisateur $user */
  124.         $user $this->container->get('security.token_storage')->getToken()->getUser();
  125.         $emailUser $user->getEmail();
  126.         $smtpEmail       $user->getSmtpEmail();
  127.         $smtpPassword    $user->getSmtpPassword();
  128.         $smtpDisplayName $user->getSmtpDisplayName();
  129.         if (!$smtpEmail || !$smtpPassword) {
  130.             return 'Aucun SMTP configuré pour votre compte. Veuillez renseigner vos paramètres SMTP dans votre profil utilisateur.';
  131.         }
  132.         /** @var \Twig\Environment $twig */
  133.         $twig $this->container->get('twig');
  134.         $html $twig->render('emails/email_layout.html.twig', [
  135.             'prospect' => $prospect,
  136.             'message'  => $message,
  137.         ]);
  138.         $email = (new Email())
  139.             ->to($prospect->getEmprunteurEmail())
  140.             ->replyTo($emailUser)
  141.             ->subject($subject)
  142.             ->from(new Address(
  143.                 $smtpEmail,
  144.                 $smtpDisplayName ?: $smtpEmail
  145.             ))
  146.             ->html($html)
  147.         ;
  148.         if (isset($emailCopy)) {
  149.             $email->addCc($emailCopy);
  150.         }
  151.         $dsn sprintf(
  152.             'smtp://%s:%s@smtp.office365.com:587/?allow_peer=0',
  153.             rawurlencode($smtpEmail),
  154.             $smtpPassword
  155.         );
  156.         $transport     = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
  157.         $dynamicMailer = new \Symfony\Component\Mailer\Mailer($transport);
  158.         try {
  159.             $dynamicMailer->send($email);
  160.             return true;
  161.         } catch (TransportExceptionInterface $e) {
  162.             return 'Erreur envoi SMTP : ' $e->getMessage();
  163.         }
  164.     }
  165.     public function alertProspectATraiter(Prospect $prospectUtilisateur $negociateur): bool
  166.     {
  167.         if (!$prospect->getEmprunteurEmail()) {
  168.             return false;
  169.         }
  170.         // Sujet neutre et cohérent
  171.         $subject sprintf('%s - Votre demande a bien été prise en compte'$prospect->getEntreprise());
  172.         // Message simple, sans répétition, sans phrase inutile
  173.         $message sprintf(
  174.             "%s va vous rappeler prochainement pour échanger sur votre projet immobilier.",
  175.             trim($negociateur->getPrenom().' '.$negociateur->getNom())
  176.         );
  177.         // Utilisation du NOUVEAU TEMPLATE email_atraiter.html.twig
  178.         $email = (new TemplatedEmail())
  179.             ->to($prospect->getEmprunteurEmail())
  180.             ->subject($subject)
  181.             ->htmlTemplate('emails/email_atraiter.html.twig')
  182.             ->context([
  183.                 'prospect' => $prospect,
  184.                 'message' => nl2br($message),
  185.             ]);
  186.         $email->from(new Address('mailer@zada.ai''LK1 Immobilier'));
  187.         $email->getHeaders()->addTextHeader('X-Transport''main');
  188.         try {
  189.             $this->mailer->send($email);
  190.             return true;
  191.         } catch (TransportExceptionInterface $e) {
  192.             return false;
  193.         }
  194.     }
  195.     public function alertAuteurProspect(int $prospectIdint $auteurIdUtilisateur $userConnected)
  196.     {
  197.         $auteur $this->utilisateurRepository->find($auteurId);
  198.         $prospect $this->prospectRepository->find($prospectId);
  199.         if (!$auteur || !$prospect) {
  200.             return false;
  201.         }
  202.         $pdfPath $this->creationPdf->createPDF($prospect'/''file');
  203.         $email = (new TemplatedEmail())
  204.             ->from(new Address('mailer@zada.ai''LK1'))
  205.             ->to($auteur->getEmail())
  206.             ->subject($prospect->getEntreprise() . ' : nouveau contact à traiter')
  207.             ->htmlTemplate('emails/email_nouveau_contact.html.twig')
  208.             ->context([
  209.                 'prospect' => $prospect,
  210.                 'auteur' => $auteur,
  211.             ])
  212.             ->attachFromPath($pdfPath);
  213.         try {
  214.             $this->mailer->send($email);
  215.             if ($pdfPath) {
  216.                 if (is_file($pdfPath)) {
  217.                     unlink($pdfPath);
  218.                 }
  219.             }
  220.             $this->addNotificationForAdmins($prospect$auteur$userConnected);
  221.     
  222.             return true;
  223.         } catch (TransportExceptionInterface $e) {
  224.             if ($pdfPath) {
  225.                 if (is_file($pdfPath)) {
  226.                     unlink($pdfPath);
  227.                 }
  228.             }
  229.             return false;
  230.         }
  231.     }
  232.     /**
  233.      * Méthode pour notifier les SUPERADMIN d'une demande de suppression de programme
  234.      */
  235.     public function alertDemandeSuppression(Programme $programmeUtilisateur $userConnected)
  236.     {
  237.         $entreprise $programme->getEntreprise();
  238.         if (!$entreprise) {
  239.             return false;
  240.         }
  241.         $superAdmins $this->utilisateurRepository->createQueryBuilder('u')
  242.             ->where('u.entreprise = :entreprise')
  243.             ->andWhere('u.roles LIKE :roleSuperAdmin')
  244.             ->setParameter('entreprise'$entreprise)
  245.             ->setParameter('roleSuperAdmin''%ROLE_SUPERADMIN%')
  246.             ->getQuery()
  247.             ->getResult();
  248.         foreach ($superAdmins as $admin) {
  249.             $infoSuivi = new InfosSuivi();
  250.             $infoSuivi->setUtilisateur($admin);
  251.             $infoSuivi->setType('suppr');
  252.             $infoSuivi->setDescription('[user] a fait une [demande de suppression] pour le programme [programme].');
  253.             $infoSuivi->setDate(new \DateTime());
  254.             $infoSuivi->setLu(false);
  255.             $infoSuivi->setConnectedUser($userConnected);
  256.             $infoSuivi->setProgramme($programme);
  257.             $this->em->persist($infoSuivi);
  258.         }
  259.         $this->em->flush();
  260.         return true;
  261.     }
  262.     public function alertRapportATraiter(array $admins, array $prospects)
  263.     {
  264.         if (empty($admins)) {
  265.             return array(
  266.                 'success' => false,
  267.                 'errors' => array('Aucun admin éligible pour recevoir le rapport.')
  268.             );
  269.         }
  270.         // Construire le contenu du rapport
  271.         $lines = array();
  272.         if (empty($prospects)) {
  273.             $lines[] = "Aucun prospect A TRAITER cliqué aujourd'hui.";
  274.         } else {
  275.             $lines[] = "";
  276.             foreach ($prospects as $prospect) {
  277.                 /** @var \App\Entity\Prospect $prospect */
  278.                 $lines[] = sprintf(
  279.                     '- #%d %s %s (%s) - clic : %s',
  280.                     $prospect->getId(),
  281.                     $prospect->getEmprunteurNom(),
  282.                     $prospect->getEmprunteurPrenom(),
  283.                     $prospect->getEmprunteurEmail(),
  284.                     $prospect->getDateCliqueATraiter()
  285.                         ? $prospect->getDateCliqueATraiter()->format('d/m/Y H:i')
  286.                         : 'N/A'
  287.                 );
  288.             }
  289.         }
  290.         $lines[] = "";
  291.         $messageText implode("\n"$lines);
  292.         // User connecté uniquement pour le reply-to (pas pour le SMTP)
  293.         $emailUser null;
  294.         if ($this->container->has('security.token_storage')
  295.             && $this->container->get('security.token_storage')->getToken()
  296.         ) {
  297.             $user $this->container->get('security.token_storage')->getToken()->getUser();
  298.             if ($user instanceof Utilisateur && $user->getEmail()) {
  299.                 $emailUser $user->getEmail();
  300.             }
  301.         }
  302.         // Rendu du template Twig
  303.         /** @var \Twig\Environment $twig */
  304.         $twig $this->container->get('twig');
  305.         $html $twig->render('emails/rapport.html.twig', [
  306.             'prospect' => null,
  307.             'message'  => $messageText,
  308.         ]);
  309.         $success false;
  310.         $errors  = array();
  311.         foreach ($admins as $admin) {
  312.             if (!method_exists($admin'getEmail') || !$admin->getEmail()) {
  313.                 $errors[] = 'Admin sans email valide.';
  314.                 continue;
  315.             }
  316.             $email = (new Email())
  317.                 ->from(new Address('mailer@zada.ai''LK1'))
  318.                 ->to($admin->getEmail())
  319.                 ->subject('Rapport quotidien - Prospects A TRAITER cliqués aujourd\'hui')
  320.                 ->html($html);
  321.             if ($emailUser) {
  322.                 $email->replyTo($emailUser);
  323.             }
  324.             // Utilise le transport par défaut "main"
  325.             $email->getHeaders()->addTextHeader('X-Transport''main');
  326.             try {
  327.                 $this->mailer->send($email);
  328.                 $success true;
  329.             } catch (TransportExceptionInterface $e) {
  330.                 $errors[] = sprintf(
  331.                     'Erreur pour %s : %s',
  332.                     $admin->getEmail(),
  333.                     $e->getMessage()
  334.                 );
  335.             }
  336.         }
  337.         return array(
  338.             'success' => $success,
  339.             'errors'  => $errors,
  340.         );
  341.     }
  342.     private function addNotificationForAdmins(Prospect $prospect, ?Utilisateur $auteurUtilisateur $userConnected)
  343.     {
  344.         $entreprise $auteur $auteur->getEntreprise() : null;
  345.         $queryBuilder $this->utilisateurRepository->createQueryBuilder('u');
  346.     
  347.         if ($entreprise) {
  348.             $queryBuilder->where('u.entreprise = :entreprise')
  349.                 ->setParameter('entreprise'$entreprise);
  350.         }
  351.     
  352.         $queryBuilder->andWhere(
  353.             $queryBuilder->expr()->orX(
  354.                 $queryBuilder->expr()->like('u.roles'':rolesAdmin'),
  355.                 $queryBuilder->expr()->like('u.roles'':rolesSuperAdmin')
  356.             )
  357.         )
  358.         ->setParameter('rolesAdmin''%ROLE_ADMIN%')
  359.         ->setParameter('rolesSuperAdmin''%ROLE_SUPERADMIN%');
  360.     
  361.         if (in_array('ROLE_COMMERCIAL'$auteur->getRoles())) {
  362.             $queryBuilder->orWhere('u.roles LIKE :rolesDirecteur')
  363.                 ->setParameter('rolesDirecteur''%ROLE_DIRECTEUR%');
  364.         }
  365.         if (in_array('ROLE_PARTENAIRE'$auteur->getRoles())) {
  366.             $queryBuilder->orWhere('u.roles LIKE :rolesResponsable')
  367.                 ->setParameter('rolesResponsable''%ROLE_RESPONSABLE%');
  368.         }
  369.         $admins $queryBuilder->getQuery()->getResult();
  370.     
  371.         foreach ($admins as $admin) {
  372.             $infoSuivi = new InfosSuivi();
  373.             $infoSuivi->setUtilisateur($admin);
  374.             $infoSuivi->addProspect($prospect);
  375.             $infoSuivi->setType('client');
  376.             $infoSuivi->setDescription('Le client [prospect] a été attribué à [user] par [connectedUser]');
  377.             $infoSuivi->setDate(new \DateTime());
  378.             $infoSuivi->setLu(false);
  379.             $infoSuivi->setAuteur($auteur);
  380.             $infoSuivi->setConnectedUser($userConnected);
  381.     
  382.             $this->em->persist($infoSuivi);
  383.         }
  384.     
  385.         $this->em->flush();
  386.     }
  387. }