Feat: Implement email notification about new disposition
This commit is contained in:
@@ -40,6 +40,8 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
MAILER_DSN=null://null
|
||||
###< symfony/mailer ###
|
||||
|
||||
APP_BASE_URI=https://myep-team.ddev.site
|
||||
|
||||
APP_BPN_USER=
|
||||
APP_BPN_PASSWORD=
|
||||
APP_BPN_ENDPOINT=
|
||||
|
||||
+15
-10
@@ -9,18 +9,20 @@
|
||||
<mj-style>
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
line-height: 36px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
p {
|
||||
font-size: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
p.small {
|
||||
@@ -43,11 +45,14 @@
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
</mj-style>
|
||||
</mj-head>
|
||||
<mj-body background-color="#666666">
|
||||
<mj-hero mode="fluid-height" height="285px" background-color="#FFFFFF" padding-top="20px" padding-bottom="20px">
|
||||
<mj-image src="{{ email.image('@images/logo.png') }}" width="200px" align="left" alt="Logo E&P" />
|
||||
<mj-hero mode="fluid-height" height="285px" background-color="#FFFFFF" padding-top="10px" padding-bottom="10px">
|
||||
<mj-image src="{{ email.image('@images/logo.png') }}" width="160px" align="left" alt="Logo E&P" />
|
||||
</mj-hero>
|
||||
<mj-section background-color="#FFFFFF" border-top="1px solid #3d8ccb">
|
||||
<mj-column>
|
||||
@@ -65,7 +70,7 @@
|
||||
</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores
|
||||
earum eius fugiat in nesciunt quas quidem vitae?
|
||||
<strong>earum eius fugiat in nesciunt quas quidem vitae</strong>?
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="button">
|
||||
|
||||
@@ -18,6 +18,9 @@ framework:
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
router:
|
||||
default_uri: '%env(APP_BASE_URI)%'
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
|
||||
@@ -13,10 +13,10 @@ framework:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
sync: 'sync://'
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: sync
|
||||
Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
|
||||
@@ -4,17 +4,20 @@ namespace App\Controller\Admin\Application;
|
||||
|
||||
use App\Entity\Application;
|
||||
use App\Entity\Disposition;
|
||||
use App\Event\DispositionCreatedEvent;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class DisposeController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
@@ -30,6 +33,8 @@ class DisposeController extends AbstractController
|
||||
$this->entityManager->remove($application);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new DispositionCreatedEvent($disposition), DispositionCreatedEvent::NAME);
|
||||
|
||||
$this->addFlash('success', 'Der Teamer wurde eingeteilt');
|
||||
$this->logger->info('Create disposition', [
|
||||
'disposition_id' => $disposition->getId(),
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Email;
|
||||
|
||||
use App\Entity\User;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class WelcomeEmailMailer
|
||||
{
|
||||
public function __construct(private readonly Mailer $mailer, private readonly LoggerInterface $logger)
|
||||
{}
|
||||
|
||||
public function send(User $user): void
|
||||
{
|
||||
$this->mailer->createAndSendEmail([
|
||||
'user' => $user,
|
||||
], [
|
||||
'to' => $user->getEmail(),
|
||||
'subject' => 'Willkommen bei MyE&P Team',
|
||||
'template' => 'email/welcome.html.twig',
|
||||
]);
|
||||
|
||||
$this->logger->info('Send welcome email', [
|
||||
'user_id' => $user->getId(),
|
||||
'user_email' => $user->getEmail(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -51,11 +51,10 @@ class Destination implements TimestampableEntityInterface, SoftDeletableEntityIn
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('%s - %s: %s, %s',
|
||||
return sprintf('%s - %s %s',
|
||||
$this->getDateFrom()->format('d.m.y'),
|
||||
$this->getDateTo()->format('d.m.y'),
|
||||
$this->getProduct(),
|
||||
$this->getHotel()
|
||||
$this->getProduct()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Entity\Disposition;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
class DispositionCreatedEvent extends Event
|
||||
{
|
||||
public const NAME = 'disposition.created';
|
||||
|
||||
public function __construct(private readonly Disposition $disposition)
|
||||
{}
|
||||
|
||||
public function getDisposition(): Disposition
|
||||
{
|
||||
return $this->disposition;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\EventListener;
|
||||
|
||||
use App\Email\Mailer;
|
||||
use App\Event\DispositionCreatedEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class EmailNotificationSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(private readonly Mailer $mailer)
|
||||
{
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
DispositionCreatedEvent::NAME => 'onDispositionCreated',
|
||||
];
|
||||
}
|
||||
|
||||
public function onDispositionCreated(DispositionCreatedEvent $event): void
|
||||
{
|
||||
$disposition = $event->getDisposition();
|
||||
$teamer = $disposition->getTeamer();
|
||||
|
||||
$this->mailer->createAndSendEmail([
|
||||
'disposition' => $disposition,
|
||||
], [
|
||||
'to' => $teamer->getCommunication()->getEmail(),
|
||||
'subject' => 'Dein Einsatz wurde angenommen',
|
||||
'template' => 'email/application_accepted.html.twig',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
Destination
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
||||
{{ assignment.destination.product }}, {{ assignment.destination.hotel }}
|
||||
{{ assignment.destination.product }}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Destination
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
||||
{{ assignment.destination.product }}, {{ assignment.destination.hotel }}
|
||||
{{ assignment.destination.product }}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends 'email/layout.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>
|
||||
Herzlichen Glückwunsch!
|
||||
</h1>
|
||||
<p>
|
||||
<strong>
|
||||
Dein Einsatz <a href="{{ url('app_teamer_disposition_detail', { 'uuid': disposition.uuid }) }}">{{ disposition.assignment.destination}}</a>
|
||||
wurde angenommen!
|
||||
</strong>
|
||||
</p>
|
||||
<p>
|
||||
Schau einmal in das <a href="{{ url('app_teamer_disposition_detail', { 'uuid': disposition.uuid }) }}">My E&P-Team Portal</a>,
|
||||
um die Einsatzdetails einzusehen und deinen Honorarvertrag zu unterschreiben.
|
||||
</p>
|
||||
<p>
|
||||
Mit dem Erhalt dieser E-Mail hast du 7 Tage Zeit deinen Einsatz zu bestätigen, indem du den unterschriebenen
|
||||
Vertrag hochlädst. Ist diese Frist vergangen, wird der Einsatz für deine Teamkolleg:innen freigeschaltet.
|
||||
</p>
|
||||
<p>
|
||||
Schön, dass du dabei bist und ganz viel Spaß in den Bergen! 😊
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ url('app_teamer_index') }}" class="button">
|
||||
Zum Portal
|
||||
</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -105,20 +105,22 @@
|
||||
<style type="text/css">
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
line-height: 36px;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
@@ -146,6 +148,10 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -158,7 +164,7 @@
|
||||
<tbody>
|
||||
<tr style="vertical-align:top;">
|
||||
<td style="width:0.01%;padding-bottom:NaN%;mso-padding-bottom-alt:0;" />
|
||||
<td style="background:#FFFFFF;background-position:center center;background-repeat:no-repeat;padding:0px;padding-top:20px;padding-bottom:20px;vertical-align:top;">
|
||||
<td style="background:#FFFFFF;background-position:center center;background-repeat:no-repeat;padding:0px;padding-top:10px;padding-bottom:10px;vertical-align:top;">
|
||||
<!--[if mso | IE]><table border="0" cellpadding="0" cellspacing="0" style="width:600px;" width="600" ><tr><td style=""><![endif]-->
|
||||
<div class="mj-hero-content" style="margin:0px auto;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;margin:0px;">
|
||||
@@ -172,8 +178,8 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:200px;">
|
||||
<img alt="Logo E&P" src="{{ email.image('@images/logo.png') }}" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="200" height="auto" />
|
||||
<td style="width:160px;">
|
||||
<img alt="Logo E&P" src="{{ email.image('@images/logo.png') }}" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="160" height="auto" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -209,7 +215,7 @@
|
||||
<div style="font-family:Lato, Verdana, Arial, 'Helvetica neue', sans-serif;font-size:16px;line-height:24px;text-align:left;color:#666666;">{% block body %} <h1> Lorem ipsum dolor sit amet </h1>
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores earum eius fugiat in nesciunt quas quidem vitae? </p>
|
||||
<h2> Lorem ipsum dolor </h2>
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores earum eius fugiat in nesciunt quas quidem vitae? </p>
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto culpa delectus dolores <strong>earum eius fugiat in nesciunt quas quidem vitae</strong>? </p>
|
||||
<p>
|
||||
<a href="#" class="button"> Button </a>
|
||||
</p>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{% extends 'email/layout.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>
|
||||
Willkommen bei MyE&P Team
|
||||
</h1>
|
||||
<p>
|
||||
Hallo {{ user.firstName }},
|
||||
</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid asperiores atque, commodi deleniti
|
||||
dignissimos dolorum earum ex facere facilis necessitatibus non omnis pariatur possimus quas repudiandae sit
|
||||
soluta tenetur, voluptatem.
|
||||
</p>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user