Jelajahi Sumber

Adds sales admin notification for premium trial

Implements email notification to the sales administration
team when a new structure requests an artist premium trial.

This allows the sales team to be promptly informed of new
trial requests, enabling timely follow-up and potential
conversion to paying customers.
Olivier Massot 5 bulan lalu
induk
melakukan
5160d3334b

+ 56 - 0
src/Service/Mailer/Builder/NewStructureArtistPremiumTrialRequestSalesAdminBuilder.php

@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Service\Mailer\Builder;
+
+use App\Entity\Access\Access;
+use App\Enum\Core\EmailSendingTypeEnum;
+use App\Service\Mailer\Email;
+use App\Service\Mailer\Model\MailerModelInterface;
+use App\Service\Mailer\Model\NewStructureArtistPremiumTrialRequestSalesAdminModel;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\EntityManagerInterface;
+
+/**
+ * Classe NewStructureArtistPremiumTrialRequestSalesAdminBuilder qui est chargé de construire l'Email
+ * d'information à l'administration des ventes concernant une demande d'essai artist premium pour une nouvelle structure.
+ */
+class NewStructureArtistPremiumTrialRequestSalesAdminBuilder extends AbstractBuilder implements BuilderInterface
+{
+    public function __construct(
+        private readonly EntityManagerInterface $entityManager,
+        private readonly string $opentalentNoReplyEmailAddress,
+    ) {
+    }
+
+    public function support(MailerModelInterface $mailerModel): bool
+    {
+        return $mailerModel instanceof NewStructureArtistPremiumTrialRequestSalesAdminModel;
+    }
+
+    /**
+     * @param NewStructureArtistPremiumTrialRequestSalesAdminModel $mailerModel
+     */
+    public function build(MailerModelInterface $mailerModel): ArrayCollection
+    {
+        $author = $this->entityManager->getRepository(Access::class)->find($mailerModel->getSenderId());
+
+        $context = [
+            'trialRequest' => $mailerModel->getTrialRequest(),
+        ];
+
+        $content = $this->render('shop/new-structure-artist-premium-trial-sales-admin', $context);
+
+        $email = (new Email())
+            ->setEmailEntity($this->buildEmailEntity('Nouvelle demande d\'essai Artist Premium', $author, $content))
+            ->setContent($content)
+            ->setFrom($this->opentalentNoReplyEmailAddress)
+            ->setFromName('Opentalent');
+
+        // Add recipient as a string (direct email address)
+        $this->addRecipient($email, 'adv@opentalent.fr', EmailSendingTypeEnum::TO);
+
+        return new ArrayCollection([$email]);
+    }
+}

+ 28 - 0
src/Service/Mailer/Model/NewStructureArtistPremiumTrialRequestSalesAdminModel.php

@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Service\Mailer\Model;
+
+use App\ApiResources\Shop\NewStructureArtistPremiumTrialRequest;
+
+/**
+ * Classe NewStructureArtistPremiumTrialRequestSalesAdminModel qui conserve les données pour construire le mail
+ * d'information à l'administration des ventes concernant une demande d'essai artist premium pour une nouvelle structure.
+ */
+class NewStructureArtistPremiumTrialRequestSalesAdminModel extends AbstractMailerModel implements MailerModelInterface
+{
+    private NewStructureArtistPremiumTrialRequest $trialRequest;
+
+    public function getTrialRequest(): NewStructureArtistPremiumTrialRequest
+    {
+        return $this->trialRequest;
+    }
+
+    public function setTrialRequest(NewStructureArtistPremiumTrialRequest $trialRequest): self
+    {
+        $this->trialRequest = $trialRequest;
+
+        return $this;
+    }
+}

+ 22 - 0
src/Service/Shop/ShopService.php

@@ -203,6 +203,9 @@ class ShopService
         // Start the artist premium trial
         $this->trial->startArtistPremiumTrialForNewStructure($organization, $trialRequest);
 
+        // Send email to sales administration
+        $this->sendMailToSalesAdministration($trialRequest);
+
         $this->logger->info('Successfully processed NewStructureArtistPremiumTrial for token: '.$token);
     }
 
@@ -261,6 +264,7 @@ class ShopService
         $organizationCreationRequest->setSiretNumber($trialRequest->getSiren());
         $organizationCreationRequest->setPhoneNumber($trialRequest->getRepresentativePhone());
         $organizationCreationRequest->setSubdomain($trialRequest->getStructureIdentifier());
+        $organizationCreationRequest->setSendConfirmationEmailAt($trialRequest->getRepresentativeEmail());
 
         // Set default values
         $organizationCreationRequest->setProduct(SettingsProductEnum::FREEMIUM);
@@ -271,4 +275,22 @@ class ShopService
         return $organizationCreationRequest;
     }
 
+    /**
+     * Envoie un email à l'administration des ventes pour informer d'une nouvelle demande d'essai artist premium.
+     *
+     * @param NewStructureArtistPremiumTrialRequest $trialRequest La demande d'essai
+     *
+     * @throws TransportExceptionInterface
+     */
+    protected function sendMailToSalesAdministration(NewStructureArtistPremiumTrialRequest $trialRequest): void
+    {
+        // Create the email model
+        $model = new Model\NewStructureArtistPremiumTrialRequestSalesAdminModel();
+        $model
+            ->setTrialRequest($trialRequest)
+            ->setSenderId(AccessIdsEnum::ADMIN_2IOPENSERVICE->value);
+
+        // Send the email to the sales administration
+        $this->mailer->main($model);
+    }
 }

+ 105 - 0
templates/emails/shop/new-structure-artist-premium-trial-sales-admin.html.twig

@@ -0,0 +1,105 @@
+{% extends '@templates/emails/base.html.twig' %}
+
+{% block title %}Nouvelle demande d'essai Artist Premium{% endblock %}
+
+{% block content %}
+    <h1>Nouvelle demande d'essai Artist Premium</h1>
+
+    <p>Une nouvelle structure a demandé à créer une structure et à démarrer une période d'essai artist premium.</p>
+
+    <h2>Informations sur la structure</h2>
+    <table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
+        <tr style="background-color: #f2f2f2;">
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Champ</th>
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Valeur</th>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Nom de la structure</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.structureName }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Adresse</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.address }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Complément d'adresse</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.addressComplement }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Code postal</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.postalCode }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Ville</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.city }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Email de la structure</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.structureEmail }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Type de structure</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.structureType }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Statut juridique</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.legalStatus }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Identifiant de la structure</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.structureIdentifier }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">SIREN</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.siren }}</td>
+        </tr>
+    </table>
+
+    <h2>Informations sur le représentant</h2>
+    <table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
+        <tr style="background-color: #f2f2f2;">
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Champ</th>
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Valeur</th>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Prénom</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.representativeFirstName }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Nom</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.representativeLastName }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Fonction</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.representativeFunction }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Email</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.representativeEmail }}</td>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Téléphone</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.representativePhone }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Représentant légal</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.legalRepresentative ? 'Oui' : 'Non' }}</td>
+        </tr>
+    </table>
+
+    <h2>Autres informations</h2>
+    <table style="width: 100%; border-collapse: collapse;">
+        <tr style="background-color: #f2f2f2;">
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Champ</th>
+            <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Valeur</th>
+        </tr>
+        <tr>
+            <td style="border: 1px solid #ddd; padding: 8px;">Conditions acceptées</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.termsAccepted ? 'Oui' : 'Non' }}</td>
+        </tr>
+        <tr style="background-color: #f2f2f2;">
+            <td style="border: 1px solid #ddd; padding: 8px;">Inscription à la newsletter</td>
+            <td style="border: 1px solid #ddd; padding: 8px;">{{ trialRequest.newsletterSubscription ? 'Oui' : 'Non' }}</td>
+        </tr>
+    </table>
+{% endblock %}