<?php
namespace App\Service;
use App\Entity\Historique;
use App\Entity\InfosSuivi;
use App\Entity\Lot;
use App\Entity\Programme;
use App\Entity\Prospect;
use App\Entity\Impression;
use App\Entity\Utilisateur;
use App\Repository\ProspectRepository;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Address;
use App\Repository\UtilisateurRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
class Notification
{
protected $doctrine;
protected $container;
protected $mailer;
protected $utilisateurRepository;
protected $prospectRepository;
protected $router;
private $creationPdf;
private $em;
public function __construct(ContainerInterface $container, ManagerRegistry $doctrine, MailerInterface $mailer, UtilisateurRepository $utilisateurRepository, ProspectRepository $prospectRepository, UrlGeneratorInterface $router, CreationPdf $creationPdf, EntityManagerInterface $em)
{
$this->container = $container;
$this->doctrine = $doctrine;
$this->mailer = $mailer;
$this->utilisateurRepository = $utilisateurRepository;
$this->prospectRepository = $prospectRepository;
$this->router = $router;
$this->creationPdf = $creationPdf;
$this->em = $em;
}
public function alertInterne(Prospect $prospect, Impression $impression, Lot $lot, UtilisateurRepository $utilisateurRepository)
{
$utilisateurs = $utilisateurRepository->findBy( ['notification' => true]);
$destinataires = [];
foreach($utilisateurs as $utilisateur){
$destinataires[] = new Address($utilisateur->getEmail());
}
$email = (new TemplatedEmail())
->from(new Address('mailer@zada.ai', 'Élise Bala'))
->replyTo($prospect->getEmprunteurEmail())
->to(...$destinataires)
->subject($prospect->getEntreprise() . ' : nouveau retour de prospect')
->htmlTemplate('emails/email_impression.html.twig')
->context([
'prospect' => $prospect,
'impression' => $impression,
'lot' => $lot
])
;
try {
$this->mailer->send($email);
return true;
} catch (TransportExceptionInterface $e) {
return false;
}
}
public function alertVisite(Prospect $prospect, UtilisateurRepository $utilisateurRepository, string $senderEmail, Historique $lastHistorique)
{
$SUPERADMINs = $utilisateurRepository->createQueryBuilder('u')
->where('u.email LIKE :email')
->andWhere('u.notification = true')
->setParameters(['email' => $senderEmail])
->getQuery()
->getResult();
$destinataires = [];
foreach ($SUPERADMINs as $SUPERADMIN) {
$destinataires[] = new Address($SUPERADMIN->getEmail());
}
$destinataires = array_unique($destinataires, SORT_REGULAR);
$email = (new TemplatedEmail())
->replyTo($prospect->getEmprunteurEmail())
->to(...$destinataires)
->subject($prospect->getEntreprise() . ' : nouvelle visite')
->htmlTemplate('emails/email_visite.html.twig')
->context([
'prospect' => $prospect,
'lastHistorique' => $lastHistorique
]);
$email->from(new Address('mailer@zada.ai', 'LK1'));
$email->getHeaders()->addTextHeader('X-Transport', 'main');
$infoSuivi = new InfosSuivi();
$infoSuivi->setUtilisateur($prospect->getAuteur());
$infoSuivi->addProspect($prospect);
$infoSuivi->setHistorique($lastHistorique);
$infoSuivi->setType('visite');
$infoSuivi->setDescription('[prospect] a [visite] son espace public.');
$infoSuivi->setDate(new \DateTime());
$infoSuivi->setLu(false);
$this->em->persist($infoSuivi);
$this->em->flush();
try {
$this->mailer->send($email);
return true;
} catch (TransportExceptionInterface $e) {
return false;
}
}
public function alertProspect(Prospect $prospect, Request $request)
{
$subject = $request->request->get('_mail_subject');
$message = $request->request->get('_mail_message');
$addCopy = $request->request->get('_mail_copy');
if (isset($addCopy)) {
$emailCopy = $prospect->getCoEmprunteurEmail();
}
/** @var Utilisateur $user */
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$emailUser = $user->getEmail();
$smtpEmail = $user->getSmtpEmail();
$smtpPassword = $user->getSmtpPassword();
$smtpDisplayName = $user->getSmtpDisplayName();
if (!$smtpEmail || !$smtpPassword) {
return 'Aucun SMTP configuré pour votre compte. Veuillez renseigner vos paramètres SMTP dans votre profil utilisateur.';
}
/** @var \Twig\Environment $twig */
$twig = $this->container->get('twig');
$html = $twig->render('emails/email_layout.html.twig', [
'prospect' => $prospect,
'message' => $message,
]);
$email = (new Email())
->to($prospect->getEmprunteurEmail())
->replyTo($emailUser)
->subject($subject)
->from(new Address(
$smtpEmail,
$smtpDisplayName ?: $smtpEmail
))
->html($html)
;
if (isset($emailCopy)) {
$email->addCc($emailCopy);
}
$dsn = sprintf(
'smtp://%s:%s@smtp.office365.com:587/?allow_peer=0',
rawurlencode($smtpEmail),
$smtpPassword
);
$transport = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
$dynamicMailer = new \Symfony\Component\Mailer\Mailer($transport);
try {
$dynamicMailer->send($email);
return true;
} catch (TransportExceptionInterface $e) {
return 'Erreur envoi SMTP : ' . $e->getMessage();
}
}
public function alertProspectATraiter(Prospect $prospect, Utilisateur $negociateur): bool
{
if (!$prospect->getEmprunteurEmail()) {
return false;
}
// Sujet neutre et cohérent
$subject = sprintf('%s - Votre demande a bien été prise en compte', $prospect->getEntreprise());
// Message simple, sans répétition, sans phrase inutile
$message = sprintf(
"%s va vous rappeler prochainement pour échanger sur votre projet immobilier.",
trim($negociateur->getPrenom().' '.$negociateur->getNom())
);
// Utilisation du NOUVEAU TEMPLATE email_atraiter.html.twig
$email = (new TemplatedEmail())
->to($prospect->getEmprunteurEmail())
->subject($subject)
->htmlTemplate('emails/email_atraiter.html.twig')
->context([
'prospect' => $prospect,
'message' => nl2br($message),
]);
$email->from(new Address('mailer@zada.ai', 'LK1 Immobilier'));
$email->getHeaders()->addTextHeader('X-Transport', 'main');
try {
$this->mailer->send($email);
return true;
} catch (TransportExceptionInterface $e) {
return false;
}
}
public function alertAuteurProspect(int $prospectId, int $auteurId, Utilisateur $userConnected)
{
$auteur = $this->utilisateurRepository->find($auteurId);
$prospect = $this->prospectRepository->find($prospectId);
if (!$auteur || !$prospect) {
return false;
}
$pdfPath = $this->creationPdf->createPDF($prospect, '/', 'file');
$email = (new TemplatedEmail())
->from(new Address('mailer@zada.ai', 'LK1'))
->to($auteur->getEmail())
->subject($prospect->getEntreprise() . ' : nouveau contact à traiter')
->htmlTemplate('emails/email_nouveau_contact.html.twig')
->context([
'prospect' => $prospect,
'auteur' => $auteur,
])
->attachFromPath($pdfPath);
try {
$this->mailer->send($email);
if ($pdfPath) {
if (is_file($pdfPath)) {
unlink($pdfPath);
}
}
$this->addNotificationForAdmins($prospect, $auteur, $userConnected);
return true;
} catch (TransportExceptionInterface $e) {
if ($pdfPath) {
if (is_file($pdfPath)) {
unlink($pdfPath);
}
}
return false;
}
}
/**
* Méthode pour notifier les SUPERADMIN d'une demande de suppression de programme
*/
public function alertDemandeSuppression(Programme $programme, Utilisateur $userConnected)
{
$entreprise = $programme->getEntreprise();
if (!$entreprise) {
return false;
}
$superAdmins = $this->utilisateurRepository->createQueryBuilder('u')
->where('u.entreprise = :entreprise')
->andWhere('u.roles LIKE :roleSuperAdmin')
->setParameter('entreprise', $entreprise)
->setParameter('roleSuperAdmin', '%ROLE_SUPERADMIN%')
->getQuery()
->getResult();
foreach ($superAdmins as $admin) {
$infoSuivi = new InfosSuivi();
$infoSuivi->setUtilisateur($admin);
$infoSuivi->setType('suppr');
$infoSuivi->setDescription('[user] a fait une [demande de suppression] pour le programme [programme].');
$infoSuivi->setDate(new \DateTime());
$infoSuivi->setLu(false);
$infoSuivi->setConnectedUser($userConnected);
$infoSuivi->setProgramme($programme);
$this->em->persist($infoSuivi);
}
$this->em->flush();
return true;
}
public function alertRapportATraiter(array $admins, array $prospects)
{
if (empty($admins)) {
return array(
'success' => false,
'errors' => array('Aucun admin éligible pour recevoir le rapport.')
);
}
// Construire le contenu du rapport
$lines = array();
if (empty($prospects)) {
$lines[] = "Aucun prospect A TRAITER cliqué aujourd'hui.";
} else {
$lines[] = "";
foreach ($prospects as $prospect) {
/** @var \App\Entity\Prospect $prospect */
$lines[] = sprintf(
'- #%d %s %s (%s) - clic : %s',
$prospect->getId(),
$prospect->getEmprunteurNom(),
$prospect->getEmprunteurPrenom(),
$prospect->getEmprunteurEmail(),
$prospect->getDateCliqueATraiter()
? $prospect->getDateCliqueATraiter()->format('d/m/Y H:i')
: 'N/A'
);
}
}
$lines[] = "";
$messageText = implode("\n", $lines);
// User connecté uniquement pour le reply-to (pas pour le SMTP)
$emailUser = null;
if ($this->container->has('security.token_storage')
&& $this->container->get('security.token_storage')->getToken()
) {
$user = $this->container->get('security.token_storage')->getToken()->getUser();
if ($user instanceof Utilisateur && $user->getEmail()) {
$emailUser = $user->getEmail();
}
}
// Rendu du template Twig
/** @var \Twig\Environment $twig */
$twig = $this->container->get('twig');
$html = $twig->render('emails/rapport.html.twig', [
'prospect' => null,
'message' => $messageText,
]);
$success = false;
$errors = array();
foreach ($admins as $admin) {
if (!method_exists($admin, 'getEmail') || !$admin->getEmail()) {
$errors[] = 'Admin sans email valide.';
continue;
}
$email = (new Email())
->from(new Address('mailer@zada.ai', 'LK1'))
->to($admin->getEmail())
->subject('Rapport quotidien - Prospects A TRAITER cliqués aujourd\'hui')
->html($html);
if ($emailUser) {
$email->replyTo($emailUser);
}
// Utilise le transport par défaut "main"
$email->getHeaders()->addTextHeader('X-Transport', 'main');
try {
$this->mailer->send($email);
$success = true;
} catch (TransportExceptionInterface $e) {
$errors[] = sprintf(
'Erreur pour %s : %s',
$admin->getEmail(),
$e->getMessage()
);
}
}
return array(
'success' => $success,
'errors' => $errors,
);
}
private function addNotificationForAdmins(Prospect $prospect, ?Utilisateur $auteur, Utilisateur $userConnected)
{
$entreprise = $auteur ? $auteur->getEntreprise() : null;
$queryBuilder = $this->utilisateurRepository->createQueryBuilder('u');
if ($entreprise) {
$queryBuilder->where('u.entreprise = :entreprise')
->setParameter('entreprise', $entreprise);
}
$queryBuilder->andWhere(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->like('u.roles', ':rolesAdmin'),
$queryBuilder->expr()->like('u.roles', ':rolesSuperAdmin')
)
)
->setParameter('rolesAdmin', '%ROLE_ADMIN%')
->setParameter('rolesSuperAdmin', '%ROLE_SUPERADMIN%');
if (in_array('ROLE_COMMERCIAL', $auteur->getRoles())) {
$queryBuilder->orWhere('u.roles LIKE :rolesDirecteur')
->setParameter('rolesDirecteur', '%ROLE_DIRECTEUR%');
}
if (in_array('ROLE_PARTENAIRE', $auteur->getRoles())) {
$queryBuilder->orWhere('u.roles LIKE :rolesResponsable')
->setParameter('rolesResponsable', '%ROLE_RESPONSABLE%');
}
$admins = $queryBuilder->getQuery()->getResult();
foreach ($admins as $admin) {
$infoSuivi = new InfosSuivi();
$infoSuivi->setUtilisateur($admin);
$infoSuivi->addProspect($prospect);
$infoSuivi->setType('client');
$infoSuivi->setDescription('Le client [prospect] a été attribué à [user] par [connectedUser]');
$infoSuivi->setDate(new \DateTime());
$infoSuivi->setLu(false);
$infoSuivi->setAuteur($auteur);
$infoSuivi->setConnectedUser($userConnected);
$this->em->persist($infoSuivi);
}
$this->em->flush();
}
}