feat: admin editable email templates

addresses #869eg7ptr
This commit is contained in:
Björn Fromme
2026-08-17 10:39:19 +02:00
parent 804dab335f
commit 3e08965e48
49 changed files with 1760 additions and 276 deletions
+15 -11
View File
@@ -2,7 +2,9 @@
namespace App\Service\Cron;
use App\Config\EmailTextKey;
use App\Email\Mailer;
use App\Email\MailPlaceholderFactory;
use App\Entity\Assignment;
use App\Entity\Disposition;
use App\Entity\Upload;
@@ -12,9 +14,16 @@ use Psr\Log\LoggerInterface;
class DispositionReminderService
{
/**
* How long before an assignment begins the reminder goes out. Also what the mail
* tells the teamer, so the two cannot disagree.
*/
private const REMINDER_LEAD_DAYS = 5;
public function __construct(
private readonly DispositionRepository $dispositionRepository,
private readonly Mailer $mailer,
private readonly MailPlaceholderFactory $placeholderFactory,
private readonly LoggerInterface $logger,
) {
}
@@ -22,7 +31,7 @@ class DispositionReminderService
public function sendDispositionReminders(): string
{
// find dispositions starting in five days from now
$dateFrom = (new \DateTimeImmutable())->modify('+5 days');
$dateFrom = (new \DateTimeImmutable())->modify(sprintf('+%d days', self::REMINDER_LEAD_DAYS));
$qb = $this->dispositionRepository->createQueryBuilder('disposition');
$dispositions = $qb
@@ -55,17 +64,12 @@ class DispositionReminderService
foreach ($dispositions as $disposition) {
/** @var Disposition $disposition */
$teamer = $disposition->getTeamer();
$assignment = $disposition->getAssignment();
$destination = $assignment->getDestination();
$this->mailer->createAndSendEmail([
'disposition' => $disposition,
'diffInDays' => 5,
], [
'to' => $teamer->getCommunication()->getEmail(),
'subject' => 'Reminder: Dein Einsatz '.$destination,
'template' => 'email/reminder_disposition.html.twig',
]);
$this->mailer->createAndSendText(
EmailTextKey::REMINDER_DISPOSITION,
$this->placeholderFactory->forDispositionReminder($disposition, self::REMINDER_LEAD_DAYS),
['to' => $teamer->getCommunication()->getEmail()],
);
}
$message = 'Sent '.$count.' disposition reminders to teamers';
+18 -11
View File
@@ -2,6 +2,7 @@
namespace App\Service\Cron;
use App\Config\EmailTextKey;
use App\Email\Mailer;
use App\Entity\Disposition;
use App\Entity\Upload;
@@ -13,10 +14,16 @@ use Psr\Log\LoggerInterface;
class UploadReminderService
{
/**
* How long before the invoice deadline the reminder goes out.
*/
private const INVOICE_REMINDER_LEAD_DAYS = 3;
public function __construct(
private readonly DispositionRepository $dispositionRepository,
private readonly Mailer $mailer,
private readonly LoggerInterface $logger,
private readonly int $invoiceUploadDeadlineDays,
) {
}
@@ -65,12 +72,10 @@ class UploadReminderService
foreach ($dispositions as $disposition) {
$teamer = $disposition->getTeamer();
$this->mailer->createAndSendEmail([
'disposition' => $disposition,
$this->mailer->createAndSendText(EmailTextKey::REMINDER_CONTRACT_UPLOAD, [
'destination' => (string) $disposition->getAssignment()->getDestination(),
], [
'to' => $teamer->getCommunication()->getEmail(),
'subject' => 'Reminder: Fehlende Dokumente',
'template' => 'email/reminder_contract_upload.html.twig',
]);
}
@@ -82,9 +87,12 @@ class UploadReminderService
public function sendInvoiceUploadReminders(): string
{
// Invoices have to be uploaded until 14 days after end of assignment. Reminder
// is sent three days before end of this period thus on the 11th day after end of assignment.
$invoiceDueDate = (new \DateTimeImmutable())->modify('-11 days');
// Invoices have to be uploaded until invoiceUploadDeadlineDays after end of
// assignment. Reminder is sent three days before end of this period, so the
// offset follows the deadline the mail itself quotes.
$invoiceDueDate = (new \DateTimeImmutable())
->modify(sprintf('-%d days', $this->invoiceUploadDeadlineDays - self::INVOICE_REMINDER_LEAD_DAYS))
;
// Find dispositions of assignments with due invoice upload
$qb = $this->dispositionRepository->createQueryBuilder('disposition');
@@ -125,12 +133,11 @@ class UploadReminderService
foreach ($dispositions as $disposition) {
$teamer = $disposition->getTeamer();
$this->mailer->createAndSendEmail([
'disposition' => $disposition,
$this->mailer->createAndSendText(EmailTextKey::REMINDER_INVOICE_UPLOAD, [
'destination' => (string) $disposition->getAssignment()->getDestination(),
'invoiceUploadDeadlineDays' => $this->invoiceUploadDeadlineDays,
], [
'to' => $teamer->getCommunication()->getEmail(),
'subject' => 'Reminder: Fehlende Dokumente',
'template' => 'email/reminder_invoice_upload.html.twig',
]);
}