feat: send season deadline summary to the office address
This commit is contained in:
1 parent
cf876ed224
commit
77986776c2
2 files changed
+31
-42
No files matched your search
@@ -7,7 +7,6 @@ use App\Config\SeasonCalendar;
|
|||||||
use App\Email\Mailer;
|
use App\Email\Mailer;
|
||||||
use App\Entity\SeasonAssignmentTask;
|
use App\Entity\SeasonAssignmentTask;
|
||||||
use App\Repository\SeasonAssignmentTaskRepository;
|
use App\Repository\SeasonAssignmentTaskRepository;
|
||||||
use App\Repository\UserRepository;
|
|
||||||
use App\Service\Season\SeasonAssignmentLabeler;
|
use App\Service\Season\SeasonAssignmentLabeler;
|
||||||
use App\Service\Season\SeasonTaskDeadlineResolver;
|
use App\Service\Season\SeasonTaskDeadlineResolver;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
@@ -32,7 +31,6 @@ class SeasonTaskReminderService
|
|||||||
private readonly SeasonTaskDeadlineResolver $deadlineResolver,
|
private readonly SeasonTaskDeadlineResolver $deadlineResolver,
|
||||||
private readonly SeasonAssignmentLabeler $labeler,
|
private readonly SeasonAssignmentLabeler $labeler,
|
||||||
private readonly SeasonCalendar $seasonCalendar,
|
private readonly SeasonCalendar $seasonCalendar,
|
||||||
private readonly UserRepository $userRepository,
|
|
||||||
private readonly Mailer $mailer,
|
private readonly Mailer $mailer,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
) {
|
) {
|
||||||
@@ -72,21 +70,15 @@ class SeasonTaskReminderService
|
|||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the two roles that carry ROLE_ADMINISTRATIVE: the repository matches roles as they are
|
// One mail to the office mailbox instead of a copy per admin: the summary is
|
||||||
// stored on the user, and nobody is ever stored with the hierarchy-granted one
|
// office-wide, not personal, so it goes to the Mailer default (APP_DEFAULT_EMAIL_TO)
|
||||||
foreach ($this->userRepository->getUsersByRoles(['ROLE_TEAM_ADMIN', 'ROLE_MANAGER']) as $user) {
|
// and no 'to' is passed here.
|
||||||
if (true === $user->isMuteNotifications()) {
|
$this->mailer->createAndSendEmail([
|
||||||
continue;
|
'violations' => $violations,
|
||||||
}
|
], [
|
||||||
|
'subject' => 'Fristen für Saisonunterlagen erreicht',
|
||||||
$this->mailer->createAndSendEmail([
|
'template' => 'email/season_deadlines.html.twig',
|
||||||
'violations' => $violations,
|
]);
|
||||||
], [
|
|
||||||
'to' => $user->getEmail(),
|
|
||||||
'subject' => 'Fristen für Saisonunterlagen erreicht',
|
|
||||||
'template' => 'email/season_deadlines.html.twig',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$message = 'Sent the season task deadline summary for '.$count.' teamers';
|
$message = 'Sent the season task deadline summary for '.$count.' teamers';
|
||||||
$this->logger->info($message);
|
$this->logger->info($message);
|
||||||
|
|||||||
@@ -13,9 +13,7 @@ use App\Entity\Embeddable\Communication;
|
|||||||
use App\Entity\SeasonAssignment;
|
use App\Entity\SeasonAssignment;
|
||||||
use App\Entity\SeasonAssignmentTask;
|
use App\Entity\SeasonAssignmentTask;
|
||||||
use App\Entity\Teamer;
|
use App\Entity\Teamer;
|
||||||
use App\Entity\User;
|
|
||||||
use App\Repository\SeasonAssignmentTaskRepository;
|
use App\Repository\SeasonAssignmentTaskRepository;
|
||||||
use App\Repository\UserRepository;
|
|
||||||
use App\Service\Cron\SeasonTaskReminderService;
|
use App\Service\Cron\SeasonTaskReminderService;
|
||||||
use App\Service\Season\SeasonAssignmentLabeler;
|
use App\Service\Season\SeasonAssignmentLabeler;
|
||||||
use App\Service\Season\SeasonTaskDeadlineResolver;
|
use App\Service\Season\SeasonTaskDeadlineResolver;
|
||||||
@@ -31,14 +29,12 @@ use Psr\Log\NullLogger;
|
|||||||
class SeasonTaskReminderServiceTest extends TestCase
|
class SeasonTaskReminderServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
private SeasonAssignmentTaskRepository&MockObject $repository;
|
private SeasonAssignmentTaskRepository&MockObject $repository;
|
||||||
private UserRepository&MockObject $userRepository;
|
|
||||||
private Mailer&MockObject $mailer;
|
private Mailer&MockObject $mailer;
|
||||||
private SeasonTaskReminderService $service;
|
private SeasonTaskReminderService $service;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->repository = $this->createMock(SeasonAssignmentTaskRepository::class);
|
$this->repository = $this->createMock(SeasonAssignmentTaskRepository::class);
|
||||||
$this->userRepository = $this->createMock(UserRepository::class);
|
|
||||||
$this->mailer = $this->createMock(Mailer::class);
|
$this->mailer = $this->createMock(Mailer::class);
|
||||||
|
|
||||||
$this->service = new SeasonTaskReminderService(
|
$this->service = new SeasonTaskReminderService(
|
||||||
@@ -49,7 +45,6 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
new HouseCatalog(['AGR' => 'Rotbach'])
|
new HouseCatalog(['AGR' => 'Rotbach'])
|
||||||
),
|
),
|
||||||
new SeasonCalendar('11-01', '04-01'),
|
new SeasonCalendar('11-01', '04-01'),
|
||||||
$this->userRepository,
|
|
||||||
$this->mailer,
|
$this->mailer,
|
||||||
new NullLogger(),
|
new NullLogger(),
|
||||||
);
|
);
|
||||||
@@ -58,7 +53,6 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
public function testTheSummaryFiresOnTheDeadlineDay(): void
|
public function testTheSummaryFiresOnTheDeadlineDay(): void
|
||||||
{
|
{
|
||||||
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
||||||
$this->userRepository->method('getUsersByRoles')->willReturn([$this->admin()]);
|
|
||||||
|
|
||||||
$this->mailer
|
$this->mailer
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
@@ -76,6 +70,28 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
$this->service->sendDeadlineSummary(new \DateTimeImmutable('2026-10-01'));
|
$this->service->sendDeadlineSummary(new \DateTimeImmutable('2026-10-01'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The summary is one office mail, not a copy per admin: it passes no recipient at all and so
|
||||||
|
* lands on the Mailer default, APP_DEFAULT_EMAIL_TO.
|
||||||
|
*/
|
||||||
|
public function testTheSummaryGoesOutOnceToTheDefaultAddress(): void
|
||||||
|
{
|
||||||
|
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
||||||
|
|
||||||
|
$this->mailer
|
||||||
|
->expects($this->once())
|
||||||
|
->method('createAndSendEmail')
|
||||||
|
->with(
|
||||||
|
$this->anything(),
|
||||||
|
$this->callback(
|
||||||
|
static fn (array $options): bool => false === array_key_exists('to', $options)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->service->sendDeadlineSummary(new \DateTimeImmutable('2026-10-01'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testTheSummaryDoesNotFireTheDayAfter(): void
|
public function testTheSummaryDoesNotFireTheDayAfter(): void
|
||||||
{
|
{
|
||||||
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
||||||
@@ -92,7 +108,6 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
public function testCoincidingDeadlinesAreReportedOnceAsTheFirst(): void
|
public function testCoincidingDeadlinesAreReportedOnceAsTheFirst(): void
|
||||||
{
|
{
|
||||||
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
||||||
$this->userRepository->method('getUsersByRoles')->willReturn([$this->admin()]);
|
|
||||||
|
|
||||||
$levels = [];
|
$levels = [];
|
||||||
|
|
||||||
@@ -115,7 +130,6 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
$task = $this->task('2026-11-01')->setDeadlineOverride2(new \DateTimeImmutable('2026-10-15'));
|
$task = $this->task('2026-11-01')->setDeadlineOverride2(new \DateTimeImmutable('2026-10-15'));
|
||||||
|
|
||||||
$this->repository->method('findOpen')->willReturn([$task]);
|
$this->repository->method('findOpen')->willReturn([$task]);
|
||||||
$this->userRepository->method('getUsersByRoles')->willReturn([$this->admin()]);
|
|
||||||
|
|
||||||
$levels = [];
|
$levels = [];
|
||||||
|
|
||||||
@@ -133,18 +147,6 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
$this->assertSame([2], $levels);
|
$this->assertSame([2], $levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAnAdminMutingNotificationsIsSkipped(): void
|
|
||||||
{
|
|
||||||
$this->repository->method('findOpen')->willReturn([$this->task('2026-11-01')]);
|
|
||||||
$this->userRepository->method('getUsersByRoles')->willReturn([
|
|
||||||
$this->admin()->setMuteNotifications(true),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->mailer->expects($this->never())->method('createAndSendEmail');
|
|
||||||
|
|
||||||
$this->service->sendDeadlineSummary(new \DateTimeImmutable('2026-10-01'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTheDigestOnlyGoesOutOnMondays(): void
|
public function testTheDigestOnlyGoesOutOnMondays(): void
|
||||||
{
|
{
|
||||||
$this->repository->expects($this->never())->method('findOpen');
|
$this->repository->expects($this->never())->method('findOpen');
|
||||||
@@ -221,9 +223,4 @@ class SeasonTaskReminderServiceTest extends TestCase
|
|||||||
|
|
||||||
return $task;
|
return $task;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function admin(): User
|
|
||||||
{
|
|
||||||
return (new User())->setEmail('[email protected]');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user