feat: send accepted teamer invoices to configurable email inbox

This commit is contained in:
Björn Fromme
2026-03-15 12:42:28 +01:00
parent 3cb5b065f4
commit 3b99757a08
13 changed files with 648 additions and 4 deletions
+12
View File
@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace App\Email;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
interface EmailAttachmentInterface
{
public function attachTo(TemplatedEmail $email): void;
}
+2 -3
View File
@@ -2,7 +2,6 @@
namespace App\Email;
use App\Model\EmailAttachmentDto;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
@@ -46,8 +45,8 @@ class Mailer
;
foreach ($config['attachments'] as $attachment) {
/* @var EmailAttachmentDto $attachment */
$email->attach($attachment->getContent(), $attachment->getName(), $attachment->getMimeType());
/* @var EmailAttachmentInterface $attachment */
$attachment->attachTo($email);
}
$this->bodyRenderer->render($email);
@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Email\Mailer;
use App\Entity\Upload;
use App\Event\DocumentConfirmedEvent;
use App\Model\EmailPathAttachmentDto;
use App\Service\Upload\DownloadNamer;
use App\Service\Upload\UploadHandler;
use Flagception\Manager\FeatureManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class DatevEmailSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly Mailer $mailer,
private readonly UploadHandler $uploadHandler,
private readonly LoggerInterface $logger,
private readonly string $datevEmailRecipient,
private readonly string $datevEmailSender,
private readonly FeatureManagerInterface $featureManager,
) {
}
public static function getSubscribedEvents(): array
{
return [
DocumentConfirmedEvent::NAME => 'onDocumentConfirmed',
];
}
public function onDocumentConfirmed(DocumentConfirmedEvent $event): void
{
if (false === $this->featureManager->isActive('datev_email')) {
return;
}
$document = $event->getDocument();
if (Upload::TYPE_INVOICE !== $document->getType()) {
return;
}
$disposition = $document->getDisposition();
if (null === $disposition) {
$this->logger->warning('DATEV email skipped: document has no disposition', [
'document' => $document->getId(),
]);
return;
}
$teamer = $disposition->getTeamer();
if (null === $teamer) {
$this->logger->warning('DATEV email skipped: disposition has no teamer', [
'document' => $document->getId(),
]);
return;
}
$path = $this->uploadHandler->getUploadFilepath($document);
if (false === file_exists($path)) {
$this->logger->error('DATEV email skipped: attachment file not found', [
'document' => $document->getId(),
'path' => $path,
]);
return;
}
$filename = (new DownloadNamer())->nameForTeamer($document, $teamer);
$attachment = new EmailPathAttachmentDto($path, $filename);
$this->mailer->createAndSendEmail([
'disposition' => $disposition,
], [
'to' => $this->datevEmailRecipient,
'from' => $this->datevEmailSender,
'subject' => 'E&P Team Honorarnote '.$teamer,
'template' => 'email/datev_invoice.html.twig',
'attachments' => [
$attachment,
],
]);
}
}
+11 -1
View File
@@ -1,8 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Model;
class EmailAttachmentDto
use App\Email\EmailAttachmentInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
class EmailAttachmentDto implements EmailAttachmentInterface
{
public function __construct(
private readonly string $name,
@@ -25,4 +30,9 @@ class EmailAttachmentDto
{
return $this->mimeType;
}
public function attachTo(TemplatedEmail $email): void
{
$email->attach($this->content, $this->name, $this->mimeType);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Model;
use App\Email\EmailAttachmentInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
class EmailPathAttachmentDto implements EmailAttachmentInterface
{
public function __construct(
private readonly string $path,
private readonly string $name,
private readonly string $mimeType = 'application/pdf',
) {
}
public function getPath(): string
{
return $this->path;
}
public function getName(): string
{
return $this->name;
}
public function getMimeType(): string
{
return $this->mimeType;
}
public function attachTo(TemplatedEmail $email): void
{
$email->attachFromPath($this->path, $this->name, $this->mimeType);
}
}