Repository: urlaubsverwaltung/urlaubsverwaltung (java)
Issue: Kein ics-Anhang in der Bestätigungs-Mail bei Urlauben ohne Genehmigungsprozess
**Describe the bug**
Bei Urlauben **mit** Genehmigungsprozess bekommt der Antragsteller nach der Genehmigung eine "Deine Abwesenheit wurde genehmigt"-Mail  mit einem calender.ics im Anhang.
Bei Urlauben **ohne** Genehmigungsprozess bekommt der Antragsteller eine "Deine Abwesenheit wurde erstellt"-Mail, die aber keinen .ics-Anhang enthält.

**Expected behavior**
Bestätigungsmails **mit** .ics-Anhang auch bei Urlauben ohne Genehmigungsprozess
Pull request description: Add ical to confirmation allowed directly
closes #4016

<!--

Thanks for contributing to the Urlaubsverwaltung.
Please review the following notes before submitting you pull request.

Please look for other issues or pull requests which already work on this topic. Is somebody already on it? Do you need to synchronize?

# Security Vulnerabilities

🛑 STOP! 🛑 If your contribution fixes a security vulnerability, please do not submit it.
Instead, please open a report of a security vulnerability via
[Report a security vulnerability](https://github.com/urlaubsverwaltung/urlaubsverwaltung/security/advisories/new)


# Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please
provide a brief description of the proposed changes.

If they:
 🐞 fix a bug, please describe the broken behaviour and how the changes fix it.
    Please label with 'type: bug' and 'status: new'
    
 🎁 make an enhancement, please describe the new functionality and why you believe it's useful.
    Please label with 'type: enhancement' and 'status: new'
 
If your pull request relates to any existing issues,
please reference them by using the issue number prefixed with #.

-->


Patch:
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailService.java b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailService.java
index b72a9ed54..e9dfe98cb 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailService.java
@@ -334,6 +334,8 @@ class ApplicationMailService {
     @Async
     void sendConfirmationAllowedDirectlyByApplicant(Application application, ApplicationComment comment) {
 
+        final ByteArrayResource calendarFile = generateCalendar(application, DEFAULT, application.getPerson());
+
         final MailTemplateModelSupplier modelSupplier = locale -> Map.of(
             APPLICATION, application,
             VACATION_TYPE, application.getVacationType().getLabel(locale),
@@ -343,6 +345,7 @@ class ApplicationMailService {
             .withRecipient(application.getPerson(), NOTIFICATION_EMAIL_APPLICATION_ALLOWED)
             .withSubject("subject.application.allowedDirectly.user")
             .withTemplate("application_allowed_directly_to_applicant", modelSupplier)
+            .withAttachment(CALENDAR_ICS, calendarFile)
             .build();
         mailService.send(mailToApplicant);
 
@@ -353,6 +356,7 @@ class ApplicationMailService {
             .withRecipient(relevantColleaguesToInform)
             .withSubject("subject.application.allowed.to_colleagues", application.getPerson().getNiceName())
             .withTemplate("application_allowed_to_colleagues", modelColleaguesSupplier)
+            .withAttachment(CALENDAR_ICS, calendarFile)
             .build();
         mailService.send(mailToRelevantColleagues);
     }


Test patch:
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
index 8dbd987ef..9d48c49e2 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
@@ -875,10 +875,10 @@ class ApplicationMailServiceIT extends SingleTenantTestContainersBase {
 
         // email sent to applicant
         final MimeMessage[] inboxUser = greenMail.getReceivedMessagesForDomain(person.getEmail());
-        final Message contentUser = inboxUser[0];
-        assertThat(contentUser.getSubject()).isEqualTo("Deine Abwesenheit wurde erstellt");
-        assertThat(new InternetAddress(person.getEmail())).isEqualTo(contentUser.getAllRecipients()[0]);
-        assertThat(readPlainContent(contentUser)).isEqualTo("""
+        final MimeMessage msgUser = inboxUser[0];
+        assertThat(msgUser.getSubject()).isEqualTo("Deine Abwesenheit wurde erstellt");
+        assertThat(new InternetAddress(person.getEmail())).isEqualTo(msgUser.getAllRecipients()[0]);
+        assertThat(readPlainContent(msgUser)).isEqualTo("""
             Hallo Lieschen Mueller,
 
             dein Abwesenheitsantrag wurde erfolgreich erstellt.
@@ -898,11 +898,15 @@ class ApplicationMailServiceIT extends SingleTenantTestContainersBase {
                 Erstellungsdatum:    12.04.2021
 
 
-            Deine E-Mail-Benachrichtigungen kannst du unter https://localhost:8080/web/person/1/notifications anpassen.""");
+            Deine E-Mail-Benachrichtigungen kannst du unter https://localhost:8080/web/person/1/notifications anpassen.
+            """);
+
+        final List<AttachmentResource> attachmentsUser = getAttachments(msgUser);
+        assertThat(attachmentsUser.getFirst().getName()).contains("calendar.ics");
 
         // email sent to colleague
         final MimeMessage[] inboxColleague = greenMail.getReceivedMessagesForDomain(colleague.getEmail());
-        final Message contentColleague = inboxColleague[0];
+        final MimeMessage contentColleague = inboxColleague[0];
         assertThat(contentColleague.getSubject()).isEqualTo("Neue Abwesenheit von Lieschen Mueller");
         assertThat(new InternetAddress(colleague.getEmail())).isEqualTo(contentColleague.getAllRecipients()[0]);
         assertThat(readPlainContent(contentColleague)).isEqualTo("""
@@ -915,7 +919,11 @@ class ApplicationMailServiceIT extends SingleTenantTestContainersBase {
             Link zur Abwesenheitsübersicht: https://localhost:8080/web/absences
 
 
-            Deine E-Mail-Benachrichtigungen kannst du unter https://localhost:8080/web/person/2/notifications anpassen.""");
+            Deine E-Mail-Benachrichtigungen kannst du unter https://localhost:8080/web/person/2/notifications anpassen.
+            """);
+
+        final List<AttachmentResource> attachmentColleague = getAttachments(contentColleague);
+        assertThat(attachmentColleague.getFirst().getName()).contains("calendar.ics");
     }
 
     @Test
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceTest.java b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceTest.java
index 827817e06..b65b1f912 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceTest.java
@@ -698,6 +698,13 @@ class ApplicationMailServiceTest {
     @Test
     void sendConfirmationAllowedDirectly() {
 
+        final Settings settings = new Settings();
+        settings.setTimeSettings(new TimeSettings());
+        when(settingsService.getSettings()).thenReturn(settings);
+
+        final ByteArrayResource attachment = new ByteArrayResource("".getBytes());
+        when(iCalService.getSingleAppointment(any(), any(), any())).thenReturn(attachment);
+
         final Locale locale = JAPANESE;
         final MessageSource messageSource = mock(MessageSource.class);
         when(messageSource.getMessage("application.data.vacationType.holiday", new Object[]{}, locale)).thenReturn("vacation type label");
@@ -745,10 +752,14 @@ class ApplicationMailServiceTest {
         assertThat(mails.get(0).getSubjectMessageKey()).isEqualTo("subject.application.allowedDirectly.user");
         assertThat(mails.get(0).getTemplateName()).isEqualTo("application_allowed_directly_to_applicant");
         assertThat(mails.get(0).getTemplateModel(locale)).isEqualTo(model);
+        assertThat(mails.get(0).getMailAttachments().get().get(0).getContent()).isEqualTo(attachment);
+        assertThat(mails.get(0).getMailAttachments().get().get(0).getName()).isEqualTo("calendar.ics");
         assertThat(mails.get(1).getMailAddressRecipients()).hasValue(List.of(colleague));
         assertThat(mails.get(1).getSubjectMessageKey()).isEqualTo("subject.application.allowed.to_colleagues");
         assertThat(mails.get(1).getTemplateName()).isEqualTo("application_allowed_to_colleagues");
         assertThat(mails.get(1).getTemplateModel(locale)).isEqualTo(modelColleagues);
+        assertThat(mails.get(1).getMailAttachments().get().get(0).getContent()).isEqualTo(attachment);
+        assertThat(mails.get(1).getMailAttachments().get().get(0).getName()).isEqualTo("calendar.ics");
     }
 
     @Test